Rename the project to Particeps - #24
Conversation
|
fc4dd75 to
f19b6fb
Compare
Replace the Android Data Collector / ADC identity everywhere it is maintained: the product name, the Gradle root project, the Android applicationId and Kotlin root package, the Protocol v1 wire names, the artifact extensions, the join URI, the receiver contract, the offline analysis package, Web authoring, researcher tooling, CI and release artifacts, and the documentation. One commit, so no revision of main claims to be Particeps while emitting ADC artifacts. Protocol v1 keeps schema_version 1 and gains no second dialect. PTCCFG01 and PTCEXP01 replace ADCCFG01 and ADCEXP01 at the same eight bytes, so no binary offset moves; particeps-research-bundle-v1 replaces research-bundle-v1 and is ten bytes longer, and because it is authenticated as HPKE info and AES-GCM associated data the whole conformance corpus was regenerated rather than edited. The retired identity now has executable fail-closed coverage in Kotlin, TypeScript, and Python rather than merely being absent: retired magics, the retired bundle format, the retired join scheme, retired routing headers, and the retired media type each have a hostile vector or rejection test, and every surviving old literal carries a comment saying so. The implementation surfaced ADC-derived identifiers the issue's contract did not list, and they are renamed here rather than silently retained: the on-device frame magics and file suffixes, the corpus and dataset format identities, the Parquet column metadata keys, the key-ID derivation domains, the Keystore aliases, the WorkManager work names and tags, the Gradle system properties, the browser locale key, the Kotlin conformance package, and the receiver's npm package name. Moving applicationId to cool.linc.particeps makes this a different Android application. There is no upgrade, no migration, and no shared Keystore namespace; a pre-rename install is removed separately and its studies, keys, encrypted segments, and staged upload bodies go with it. That boundary is what made renaming the on-device names safe, and it is recorded in the README, the participant guide, and invariant 8 of the implementation contract so a later reviewer does not lift one of those renames out of context. The release signing key and certificate are unchanged. Two guards keep the rename from decaying. tools/retired_identity_audit.py fails the build on any retired spelling outside a reviewed, reasoned allow-list, and pins the applicationId, so the fresh-install boundary is tested and not only documented. The upload request vocabulary — media type, bundle format, and the seven routing header names — is now a shared corpus fixture that the Kotlin emitter and the TypeScript receiver each assert against, because it was the one part of the wire contract whose producer and only reader could be renamed independently without any test noticing. Regenerated rather than edited: the conformance corpus, the collector-catalog Kotlin contract, the demo signed envelope (the researcher name it carries is inside the Ed25519-signed canonical bytes), and the analysis lockfile. Closes #23.
f19b6fb to
f90b7cd
Compare
Emulator validation
Identity, checked on the device rather than in the source: The join scheme is routable under the new name and unroutable under the old one — the retired The launcher, the header before any study is imported, and the app label all read Particeps; Loading the demo study on the device verifies the regenerated signed envelope end to end: the Not yet done, and deliberately soRenaming the GitHub repository, and the post-rename release candidate tag. Both belong after this |
Closes #23.
Renames the entire project from Android Data Collector / ADC to Particeps — product, package identity, Protocol v1 wire names, artifact extensions, join URI, receiver contract, analysis package, Web authoring, researcher tooling, CI/release artifacts, and documentation — in one commit, so no revision of
mainclaims to be Particeps while emitting ADC artifacts.Naming contract
android-data-collectorparticepscool.linc.androiddatacollectorcool.linc.particeps.adccfg,ADCCFG01.partcfg,PTCCFG01.adcexp,ADCEXP01.partexp,PTCEXP01adc://join/v1particeps://join/v1research-bundle-v1particeps-research-bundle-v1application/vnd.adc.research-bundleapplication/vnd.particeps.research-bundleX-ADC-*X-Particeps-*adc-analysisparticeps-analysisadc_analysisparticeps_analysisadc-analysis-keys-v1particeps-analysis-keys-v1android-data-collector-<tag>.apkparticeps-<tag>.apkAdditional ADC-derived identifiers found during implementation
The issue's contract asked for these to be added rather than silently retained:
ADCMET01/ADCTXN01/ADCEVT01/ADCACT01/ADCOUT01→PTCMET01/PTCTXN01/PTCEVT01/PTCACT01/PTCOUT01, all still exactly eight ASCII bytes.events-NNNNNNNN.adcs→.ptcs,.metadata.adc/.transaction.adc/active-study.adc→.ptc. The suffix mirrors the magic in each file's header.adc-protocol-conformance-v1,adc-join-link-conformance-v1,adc-collector-catalog-v1,adc-ciphertext-inventory-v1,adc-parquet-dataset-v1,adc-quality-summary-v1,adc-validation-report-v1,adc-active-study-v1→particeps-*.adc.type/adc.unit/adc.meaning/adc.collector_id/adc.payload_type/adc.payload_schema_version/adc.clock_basis→particeps.*.adc:signer-key-id:v1:/adc:export-key-id:v1:→particeps:…(27 ASCII bytes each, was 21).HandlerThreadnames, staging-file prefixes, Gradle system properties (adc.repository.root,adc.appProjectDir), the browser locale keyadc.locale, the Kotlin conformance packageadc.conformance, and the npm package@adc/ciphertext-receiver.Fresh-install boundary
The
applicationIdchange makes this a different Android application. There is no upgrade, no migration, and no shared Keystore namespace: a pre-rename RC install must be uninstalled separately, and its studies, keys, encrypted segments, and staged upload bodies go with it. That is documented in the README, the participant guide, and as invariant 8 in the implementation contract — which also records why renaming the on-device names was safe in this commit and only in this commit.The release signing key and certificate are unchanged.
Protocol v1
schema_versionstays1; there is no v2, no alias, no compatibility decoder, no converter. The complete conformance corpus was regenerated withnode tools/generate_protocol_vectors.mjs— hand-editing it is not possible, sinceparticeps-research-bundle-v1is authenticated as HPKEinfoand AES-GCM associated data and is ten bytes longer than the name it replaces. TheADCCFG01/ADCEXP01magics are length-preserving, so no binary offset moved.The retired identity now has executable fail-closed coverage rather than merely being absent:
partcfg-retired-product-magicandbundle-retired-product-magic— valid frames with only the magic set back toADCCFG01/ADCEXP01.bundle-retired-bundle-format— an authenticated bundle whose innerformatisresearch-bundle-v1, so only the format check can reject it.join-retired-product-scheme— an otherwise-valid join link whose only defect isadc://.X-ADC-Extra,X-ADC-Bundle-Format, the retiredresearch-bundle-v1value, andapplication/vnd.adc.research-bundle.These are the only places old names survive, and each carries a comment marking it a retired-identity rejection fixture so a future sweep does not "fix" it.
Regenerated, not edited
protocol/v1/conformance-vectors.jsoncore/collector-api/.../ProtocolEventContracts.kt(tools/catalog.py generate-kotlin)app/src/debug/res/raw/demo_study_envelope.txt— re-signed, becausedemo-study.json's researcher name is inside the Ed25519-signed canonical bytesparticeps-analysis/uv.lockTwo guards against decay
The rename exposed two things nothing in the tree was checking, and both now fail the build rather than relying on care:
tools/retired_identity_audit.pysearches every tracked file for every retired spelling and fails on any match outside a reviewed allow-list that states, per file, why the old name must stay. It also pinsapplicationId/namespacetocool.linc.particepsand refuses any source reference to the retired namespace — which is the acceptance criterion "the boundary is documented and tested", expressed as something executable. Wired intoci.ymlandrelease.yml, with its own unit tests.valid.upload_requestin the shared corpus, and both sides assert against that. Both assertions were negative-checked: renaming one header on either side fails its suite.Verification
./gradlew test testDebugUnitTest lintDebug assembleDebug assembleRelease— pass:core:export:test --tests particeps.conformance.ProtocolConformanceTest— passpython3 tools/catalog.py check,tools/catalog_parity.py,tools/validate_protocol_vectors.py,tools/collector_assurance.py,tools/tests— passcheck+test+ shared TypeScript conformance +generate_protocol_vectors.mjs --check— passtypecheck+ unit + workerd — passruff check+ full offline pipeline suite — passpython3 tools/retired_identity_audit.py— pass (16 reviewed exceptions)Pixel_10_Pro, API 37)::core:storage:connectedDebugAndroidTest+:app:connectedDebugAndroidTest— 10/10 passwebpnpm run e2e(browser authoring → signed.partcfg→ the app's own Kotlin verifier accepts it) — pass.pnpm run e2e:units— pass.pnpm run e2e:one-linefails on seven collector-description strings, whichmainfails identically; unrelated and pre-existing.Not in this PR
particeps(do it after merge; badges, links, and the PagesBASE_PATHare already prepared for the new URL).CITATION.cffversion/date-released, which are intentionally absent until the first post-rename tag.