Development Timeline
A chronological log of architectural decisions, phase completions, and shipped
features. Each entry cross-references the source commit(s) so the code-truth is
one click away. The timeline feeds the /development view on the partners site;
keep it narrative-first and reader-facing.
Entries are reverse-chronological within each month. Each cluster of work has a "why" (what was the problem) and a "what shipped" so a reviewer — or future-you — can reconstruct the story without reading every commit.
June 2026 — Outreach portal + intro kit, prod cutover, frontend/admin overhaul, Pillar 2 carve-out
Two arcs this month. First (early June): the three-stream overhaul (SP-A / SP-B / SP-C) that gave each pillar its own data context, unified the UI surface, carved Pillar 2 into its own collection + on-chain program, extended soulbound attestations across all three pillars, and added two new ways for people to participate — followed by the production cutover onto the separated programs. Second (June 9–12): the outward-facing push — a public intro kit, per-contact outreach deal-rooms with seeded preview workspaces, and a refreshed demo-video + subtitle production pipeline.
2026-06-12 — Platform Demo re-recorded in a live preview workspace; media de-jargoned
The kit's "Platform Demo — Voice, Share, Market & Identity" video was
re-recorded against a real outreach preview workspace (PlantagoAI),
signed in as a fresh preview member through the same #wt= token
hand-off real contacts use. Every interaction happens live on camera —
proposal support, two anonymous votes with on-chain transaction
confirmations, an allocation vote, a supplier vote — and the video ends
on the new Identity tab showing soulbound attestations accrued from the
video's own actions (merge 93948ed7, tags prod-2026-06-12 /
prod-2026-06-12b).
Around it, a media-quality sweep: all video subtitles rebuilt from a
corrected English base in 8 languages including a new English CC track
(5ea1b2e0); narration and subtitles de-jargoned (no "Semaphore", no
"ZK proof" — say what it means); the 1-minute video's one jargon line
re-voiced; preview-access UI copy tightened (003672be). The entire
video production pipeline (recorder, narration, assembly, HyperFrames
composition, subtitle generator, session-mint utility) now lives in
tools/demo-recorder/walkthrough/ — previously it existed only on a
laptop and one script had already been lost once.
2026-06-11 — Outreach portal: per-contact deal-rooms with seeded preview workspaces
The outreach MVP (PR #118, prod-2026-06-11e; follow-ups in PR #119):
each prospective partner gets a personalized kit microsite at an
unguessable /r/:token link with engagement attribution. From there, an
email-OTP gate opens a lazily created, fully seeded tenant — the
contact lands in a live workspace as a preview member with the full
demo dataset, no setup. Preview members see a dedicated Identity
experience: a preview-access card, the soulbound-attestations panel,
and the PoH Verifier (preview-labelled, 738168e2). Kit intro +
workspace panel translated into 7 locales (b742eb6e).
2026-06-09/10 — Foundation Intro Kit + demo videos + hosting consolidation
Public, audience-keyed /kit/:segment pages on the partners site
(grants / municipal / coop / gaas / investors / generic) with
per-segment one-pagers, the shared whitepaper, and engagement recording
(PR #93, prod-2026-06-09). The kit got its first two demo videos
(PR #109) and a light "Daylight" reading theme (PRs #94/#95). Firebase
Hosting was consolidated from 9→5 prod and 11→5 staging sites under
clean foundation-global-* naming; the legacy yc. site was fully
retired (plan: docs/hosting-consolidation-plan-2026-06-09.md).
2026-06-03/05 — Production cutover onto separated programs
Production moved onto the separated Anchor programs
(identity-registry + pillar1-governance + pillar2-share), with the
registrar wallet rebound and tenant-namespaced seeding (tags
prod-2026-06-03 … prod-2026-06-05). The devnet faucet hard-banning
Cloud Functions IPs forced a treasury-wallet model: top-ups now
transfer from a funded treasury keypair instead of airdrops
(scripts/setup-treasury-wallet.sh). Ring-0 URL-driven tenant
switching landed for admin cross-tenant work.
A QA-driven bugfix sweep then closed the gaps that surfaced on staging.
2026-06 — New participation surfaces: supplier bids + crowd-sourced funding options
Two features that let participants — not just admins — seed the pipeline:
submitProductBid(functions/proposal-voting.js:727) — Pillar 3 supplier bid submission. A supplier can submit a bid against an open product request; the callable is tenant fail-closed, enforces a per-uid submission limit, and only allows the gated status transition (no arbitrary product mutation). Paired with the supplier-bid UI (7a8ba7e4, hardened in0775f962).submitAllocationOption(functions/allocations.js:954) — Pillar 2 crowd-sourced allocation options (participatory budgeting / grant proposals). Anyone in scope can propose a funding option that then becomes votable, rather than options being admin-defined only. Shipped with its UI in52b6b3b2.
2026-06 — On-chain twin backfill for products + allocations
With all three pillars now writing soulbound twins, two backfill callables bring historical records up to on-chain parity:
mintMissingProductTwins(functions/proposal-voting.js:609) — mints the missing on-chain attestation twins for past product votes, giving Pillar 3 the same on-chain coverage as P1/P2 (c8b229dc).mintMissingAllocationTwins(functions/allocations.js:867) — same backfill for Pillar 2 allocation votes/supports (951efaba).
2026-06 — QA bugfix sweep (staging)
A reviewer/QA pass over the staging deploy turned up a cluster of bugs across all three pillars, fixed in sequence:
- Firestore rules + indexes for allocations — security rules added
for
allocations,allocation_votes,allocation_signatures(1383ff1e); the composite index that the allocations index error required (49abf14d); seed writes corrected to the right collection (b9f6580d). - DLQ twin-mint
InvalidPopulationfix — Pillar 1 support recording and proposal twin-mint were landing in the dead-letter queue on anInvalidPopulationerror; fixed in12f59bac. - Product-vote badge field fix — the "Your Market" voted badge read
the wrong field; corrected after diagnostic logging (
1762e50e,49abf14d,951efaba), and the "Vote" cue now shows only on actually-votable products (34d7eb18). - Pillar 2 activity surfacing — allocation votes/supports now appear
in activity history + attestations (
82a0ba4f). - Faucet messaging — clearer message when the devnet faucet is
unavailable for an API-wallet top-up, instead of a raw 429
(
45c59532,49abf14d). - Wallet-health semantics — program accounts are now reported
healthy when rent-exempt rather than when balance > 0.1 SOL
(
dda39919). - Regression coverage for the contract bugs found in QA (
c663db55).
2026-06 — Soulbound attestations across all three pillars + populations
Attestations (introduced in May, see below) extended to a full multi-pillar identity surface:
- Per-pillar attestation types — beyond
VERIFIED_HUMAN,VOTED, andSUPPORTED_PROPOSAL, the attestation program gainedRECEIVED_SHARE(type 3,986de74a) so Pillar 2 distributions are attestable;recordDistribution+ its on-chain mirror task ship the share-receipt path (a251a181), and the GaaS PoH verifier now reportshasReceivedShare(d11e84ce). Pillar 2 allocation votes/supports and Pillar 3 product votes all mint their own twins. - Populations — population opt-in UI with nationality + location
tabs and the
setMyNationalitycallable (functions/population.js:188,b96ac7b9), feeding the UN-M49 + H3 geospatial population model that scopes on-chain governance.
2026-06 — SP-A: Pillar 2 allocation carve-out
Pillar 2 ("Your Share") split out of the shared governance path into its own data plane and on-chain program:
allocationscollection — P2 funding allocations moved out of the proposals path into a dedicated collection, with an idempotent, dry-run-capable migration script (966dd5bf,21bd7495) and a rollback-safe shape transform. The frontend reads allocations from the new collection;VotingContextis now Pillar-1-only (4d50d696).pillar2-shareAnchor program — dedicated on-chain program (evoting-backend/programs/pillar2-share/) with allocation governance instructions (create / support / activate / vote,82afc182), bound proposal IDs and validation guards (b299422f,25bd0c3a), devnet E2E (8e1566d3), and IDL synced into the Functions client (5a0d2e0b,3a6f6b76).- Dedicated P2 callables + mirror tasks — allocation callables
(
4b67ac79), on-chain mirror task handlers with stable DLQ doc IDs (7ce17791,6486af24), precondition contracts (aac254de), a share-program TS client +getShareProgramAs(b1709805), and a geo-scope validator with a guarded activate RPC (6165281c). Carve-out landed in64388601; design + plan indocs/(cc6a3c29,68dd5213).
2026-06 — SP-B: per-pillar contexts + unified UI
The frontend moved from one shared DataContext to a context per
pillar, and the three pillars' surfaces were unified visually:
- Per-pillar contexts —
VotingContext(Pillar 1),AllocationContext(Pillar 2,9dbdba0b), andMarketContext(Pillar 3,910cc59e), each owning its own live user-vote/support subscriptions. The sharedDataContextand the oldAllocationVotingcomponent were removed; an allocation-detail route added (ec4cf31a). - Unified card grids — each pillar now renders the same card-grid
pattern:
ProposalCard/ProposalDetail(P1,a5a9f10a),AllocationGrid/AllocationCard/AllocationDetail(P2,891a4e8a), andMarketplaceListing(P3,c859c811). - Shared primitives + inline confirmation —
VotedBadge,PillarActionButton, andConfirmActionModalextracted as shared primitives (19bc99c2). Population opt-in (nationality + location) shipped as a tab in the same pass (b96ac7b9). E2E coverage for the unification in15087809. Per the loose-coupling-over-DRY principle, the modal-then-inline confirmation pattern replaces the prior modal on the vote/support actions.
2026-06 — SP-C: per-pillar admin tabs + Wallet Health + Contracts
The admin panel was reorganised around the three pillars and gained operational tooling:
- Tab reorder + per-pillar tabs — Your Voice / Your Share / Your
Market tabs moved first; Action Items hidden; new tab slots added
(
2e8ef961).AdminAllocationTab(529d2681),AdminMarketTab,AdminWalletHealthTab, andAdminContractsTabimplemented (926e88d8). - Admin/ops callables —
getWalletHealth,airdropApiWallet,fundUserWallet(functions/admin-wallet.js);getContractsInfo,runPreflightTest(functions/admin-contracts.js); andadminUpdateProductStatus(functions/voter-profile.js:316), all introduced ine0da91ff. The Contracts tab is see-only — it surfacesCONTRACT_NARRATIVESco-located with the preconditionCHECKS(84726b21).
May 2026 — Soulbound attestations, all-pillar blockchain writes, research decks, legal hardening
2026-05-28 — Foundation Mobile build 3: biometric gate + passport seal + SPM migration
Three hardening features shipped to TestFlight (build 3, v1.0):
Cold-launch biometric gate — BiometricGateView.swift intercepts every fresh process start when a session exists and requires Face ID before exposing any account data. Skips automatically when biometrics are unavailable and on a fresh OTP sign-in in the same session (no double-prompt). Wired in RootView.swift via biometricGatePassed / hasSeenSignedOut state.
Passport biometric seal — After the NFC passport read and before anchorCommitment, CaptureCoordinator calls BiometricSealer.sign() over dg1Hash (SHA-256 of DG1 bytes). The resulting P-256 signature is sent as passportBiometricSeal in AnchorCommitmentRequest. Degrades gracefully — userCancelled / keyInvalidated / unavailable all produce nil and verification proceeds unaffected. This creates a cryptographic binding: the same Face-ID-protected key that seals the commitment also witnessed the specific passport identity data.
CocoaPods → Swift Package Manager migration — Full deintegration: Podfile.lock, Pods/ directory, CocoaPods xcconfig refs, [CP] build phases, and -DCOCOAPODS flags all removed from project.pbxproj. Two SPM packages added: Firebase iOS SDK (≥ 11.0.0) and NFCPassportReader (≥ 2.3.0), linking FirebaseAuth, FirebaseFirestore, FirebaseFunctions, FirebaseAppCheck, NFCPassportReader. This was the last CocoaPods dependency in the project.
SignInView cancel button — xmark button in the header, visible only on the code-entry phase, resets the OTP flow back to email entry. Prior implementation incorrectly called signOut() (no-op since SignInView is only shown when already signed out).
2026-05-27 — Soulbound attestations on Solana + GaaS PoH API (v2.6.0)
The first non-transferable on-chain identity primitive for Foundation:
Anchor program (evoting-backend/programs/attestations/) deployed to devnet at GQrFse7NiB6QdqtagGayNYwrr8zn4W4uWhji57VkKGky. Two instructions — issue_attestation and revoke_attestation — with PDAs seeded from [b"attestation", holder, attestation_type, context_hash]. Revocation is authority-locked: only the original issuing keypair can revoke. Three attestation types: VERIFIED_HUMAN (type 0, context = zero bytes), VOTED (type 1, context = proposal PDA pubkey), SUPPORTED_PROPOSAL (type 2, context = proposal PDA pubkey). Soulbound by design — PDAs are unspendable accounts; the holder cannot transfer them.
Cloud Functions pipeline:
lib/attestation-onchain.js— Anchor TS client (issueAttestationOnChain,revokeAttestationOnChain,deriveAttestationPDA)attestations.js—queryAttestationscallable (requireAuth),revokeAttestationcallable (Ring.PLATFORM_OWNER),pohAttestationsEndpoint(HTTP),revokeAllAttestationsForWalletissueAttestationOnChainTask— Cloud Task handler: mints on-chain then writes theattestationsFirestore mirror doc (doc ID:${wallet}_${type}_${contextHashHex})- Auto-issue:
VOTEDauto-issued aftermirrorVoteOnChainTasksucceeds;SUPPORTED_PROPOSALaftermirrorSupportOnChainTask
GaaS PoH API — pohAttestationsEndpoint lets third-party governance platforms verify humanity attestations via X-PoH-API-Key (SHA-256 hashed, stored in poh_api_keys collection). Returns { wallet, attestations, count, hasVerifiedHuman }. This is the first live GaaS revenue surface.
Pillar 2 blockchain write fix — AllocationVoting.tsx had a hardcoded fund.name.includes('Stockton') guard preventing all non-Stockton P2 funds from writing to Solana. Replaced with content-based option matching. All three pillars now write consistently on-chain.
CI fixes — Two bugs in deploy.yml env write steps: printf '%s' → printf '%s\n' (newline so subsequent echo >> appends to a new line), plus explicit SOLANA_ATTESTATIONS_PROGRAM_ID append (Firebase requires the param in env file even when a default is declared).
Tests — 11 new tests in functions/__tests__/attestations.test.js; total suite: 83 passing.
2026-05-24 — Competitive landscape decks + real-time sync + Mobile v1.1
Three deep-research Spectacle decks published to partners.foundation-global.com under admin-only visibility, each covering a full competitive landscape + AI wave appendix:
/present/evoting— Global E-Voting Landscape 2025. Benchmarks Swiss Post (postal voting + crypto), Estonia IVXV (open-source, national), Norway (returned to paper after reversal), Australia VEC, France VVPAT experiments, Brazil e-Urn, Voatz (security-failed mobile), and ElectionGuard (Microsoft, open-source tally crypto). Foundation comparison across 7 dimensions. Appendix: ElectionGuard integration path, Verificatum mixnet for anonymisation, ZK audit trail via Semaphore. AI wave: Slovakia 2023 deepfake, NH 2024 AI robocall, Stanford: Meta removed 7,700+ AI-generated accounts, ZKML (EZKL) as the path to mobile liveness detection without an Orb, Freedom House 18-year democratic decline / V-Dem 72% autocracy data./present/ubi— UBI & Income Distribution Landscape 2025. Covers Alaska PFD (government-run, universally popular), Macau IVP (cash vouchers), India DBT (Aadhaar-linked, 1.3B transfers), Marshall Islands on-chain UBI (first sovereign blockchain use case), Worldcoin (iris scan + WLD), GoodDollar (DeFi UBI), Circles (trust-graph currency), Self Protocol (ZK ePassport), Rarimo (cross-chain ZK identity). Foundation's ZK ePassport approach is identified as the strongest privacy-preserving option. AI wave: IMF 40% of advanced-economy jobs at high AI displacement risk, Goldman Sachs 300M jobs, McKinsey 60-70% of knowledge tasks automated within 10-15 years vs. 80 years for the Industrial Revolution, CBDC milestone (BIS: 130+ countries active, China e-CNY 260M wallets / $250B, EU Digital Euro 2026)./present/market— Collective Purchasing Landscape 2025. Covers Pinduoduo (900M users, social group buying, $35B revenue, failed Western expansion), Groupon (commission extraction model vs. Foundation's aggregation model), Costco / REI (cooperative analogues, membership lock-in), Healthcare GPOs (90% of US hospitals, 10-18% savings), India GeM (government e-marketplace, $25B volume), ConstitutionDAO (collective bidding at scale). Key finding: OpenProcurement (Apache 2.0, Ukraine / Moldova government procurement) is the best open-source reverse auction engine for Pillar 3. AI wave: Amazon 2.5M price changes/day destroys the uniform pricing that group buying requires; AI agent purchasing as the next step; US tariffs 10-145% create reshoring demand where verified collective purchasing wins.
Real-time support/vote sync fix — userSupported and userVotes in VotingContext converted from one-time getDocs to live onSnapshot subscriptions (subscribeUserSupportedProposals, subscribeUserVotedProposals in database.ts). Status now reflects immediately across sessions and devices.
Foundation Mobile v1.1 — HomeView.swift gains the Foundation web app shell: WKWebView loading https://app.foundation-global.com, window.__foundationMobileWebView = true injection, lifebuoy tech-report button, adaptive header (logo-only when web view active), "Open Foundation App" launch card. MARKETING_VERSION 1.0 → 1.1. Tagged v0.2.0.
PR #75 merged — ToS Single Account Per Person clause (v2.5.0) merged to main; staging auto-deployed. All three tasks shipped in one session: mobile web shell, support sync fix, research decks.
2026-05-21 — devMode security finding documented
docs/security-devMode-inert-guard-2026-05-21.md captures the finding that devMode: true in the Self SDK (evoting-frontend/src/components/identity/SelfEnrollment.tsx:76) makes the server-side NULLIFIER_ALREADY_USED guard inert — the same physical passport currently yields a different nullifier per enrolment in dev mode. Finding documented with three open follow-ups: (1) remove devMode flag before mainnet, (2) evaluate nullifier derivation stability across Self SDK versions, (3) consider server-side nullifier binding to the verified document hash rather than the SDK-derived value.
2026-05-15 — ToS v2.5.0: Single Account Per Person clause (PR #75)
Explicit Single Account Per Person section appended to the Foundation Terms of Service (functions/legal.js). Declares the one-human-one-account rule; names the four prohibited patterns (document reuse, multi-document enrolment, proxying, multi-account ownership); lists legal exposures (electoral fraud, identity fraud, wire/computer fraud, conspiracy); specifies enforcement consequences (suspension of all linked accounts, invalidation of votes/proposals/signatures/fund movements, abuse-registry entry, law-enforcement referral). Applies to both web client and iOS shell. ToS version bumped v2 → v3; forces re-acceptance at next sign-in for all users.
2026-05-14 — Login Analytics tab + App Check fix (v2.4.2 / v2.4.3)
AdminLoginAnalyticsTab.tsx— login activity dashboard for foundation, docs, and partners sites. Hour-of-day / day-of-week / monthly trend charts, top-10 countries with flags, per-day drill-down. Controls: 7d/30d/90d/1y range, per-site filter, IANA TZ dropdown (re-buckets all charts client-side), include-admin toggle.getLoginAnalyticscallable —Ring.TENANT_ADMIN-gated, queriessessionscollection, resolves IP → country viageoip-lite. Raw IPs never returned. 5,000-session hard cap.- v2.4.3 hotfix:
getLoginAnalyticswas missingenforceAppCheck: falsecarve-out; prod returnedunauthenticateddespite valid admin ring. Matched the pattern of the six sibling admin callables. version.tsintroduced as single source of truth for SemVer constant.
2026-05-09 — Review-week hardening sprint
A six-item push to close the regressions, latent bugs, and rough edges that surfaced as reviewers + first pilot users approached.
adminResetUserHumanitycleanup gap closed —functions/user-management.js:209-269was only clearingidentity_commitments/{uid}/commitments/*and a few user fields. The reset path now also atomically deletesflow_snapshots/foundation.register_<uid>(the doc that previously hung re-onboarding at "Loading registration…"),identity_proofsqueried byvoterId,voters/{uid}, the parentidentity_commitments/{uid}doc, andtenant_memberships/*. Refactored intoadminResetUserHumanityImpl(db, auth, callerUid, data)for direct test invocation.- 9 mock-smoke tests for hot-path Cloud Functions —
createProposalDraft(author validation),castProposalVote,castProposalSupport,getMyWallet,issueAttestationNonce,recordMobileAttestation(AAGUID mismatch coverage that would have caught this week's bug),attachSemaphoreCommitment,requestSignInCode+verifySignInCode,anchorCommitment. Reuses the existingmakeMockDbpattern fromproposal-voting.test.js. - CI deploy gate —
.github/workflows/deploy.ymlnow runscd functions && npm testas atestjob; bothdeploy-staginganddeploy-proddeclareneeds: test. Failed tests block deploy. submitProposalempty-author race fixed —evoting-frontend/src/contexts/VotingContext.tsxadds a pre-flightcurrentUser?.displayNamecheck + aclaims.sub-derived fallback so the CF never receives an empty author; submit button isdisableduntil hydration completes. Same race fixed for the auth context'slogout(nowawait clearAuth()), eliminating the sticky-relogin loop.- Demo pool slot rotation —
functions/demo-access.js:97-142switches from "lowest doc ID" to least-recently-released sorting; rotation is now observable across sequentialtryDemo/releaseDemoSlotcycles.claimSlotexported for unit tests. - Canonical fixture toolkit —
scripts/dump-fixture.mjs,scripts/seed-from-fixture.mjs,scripts/diff-projects.mjsship as the official path for capturing and applying a curated dataset. Hard guardrails: pre-write Firestore export to GCS,--dry-rundefault, prod target requires--i-understand-this-rewrites-prodplus a typed confirmation. Snapshot committed atfunctions/fixtures/canonical-fixture-2026-05-09.json— 32 proposals, 200 votes, 174 signatures, 20 voters / proofs / memberships, 14 funds, 6 distributions, 100 product requests, 2 tenants, 1 population. Applied identically to staging + prod (diff-projectstotal diff: 0). - Behavioral-econ proposal copy — 16 hand-vetted templates
replace the prior
SYNTHETICdictionary infunctions/seed-foundation-staging.mjs; finalPROPOSAL_PLANis 8 round-0 + 6 active + 1 passed + 1 discarded. Near-end voting window bumped from +5 min to +24 h to stop demos auto-expiring under reviewer eyes. Composite Firestore index added forproposals(status, voting_ends_at)soexpireVotingRoundsScheduledcan run efficiently. DemoBadgecomponent —evoting-frontend/src/components/common/DemoBadge.tsxrenders a violet pill (FlaskConicalicon) on any card or detail surface wheredemo === true, so reviewers can distinguish seeded content from real user activity at a glance. Wired intoProposalCard,ProposalDetail,MarketplaceListing,ProductRequestDetail,FundDashboard. Database mapper updated:evoting-frontend/src/lib/database.ts:178-182.- "Humanity" → "Personhood" vocabulary sweep —
IdentityProofView.tsx:148-156,registerFlow.ts:84,AdminUsersTab.tsx. "Reset humanity" is now "Reset verification." The data model retainshumanityVerifiedfor backward compatibility — only user-facing copy moved. - Google sign-in restored on partners + docs sites — three older
PRs (#25-#27) had been blocked by 33k-line merge conflicts;
recovered via surgical cherry-pick of the three critical commits
onto a fresh branch (PR #56). Adds "Continue with Google" to
LoginPage, removes the 5-app icon strip fromSidebar, removes the "Deadline: May 4, 2026" countdown footer (the application deadline has long since passed). Live onpartners.foundation-global.com+docs.foundation-global.comasprod-2026-05-09d. - Runtime SA
signBlobself-binding —scripts/setup-ci-secrets.shgained agrant_runtime_signblob()step that grantsroles/iam.serviceAccountTokenCreatorto the Cloud Run runtime SA on itself. Without this,firebase-admin'screateCustomToken()(used bytryDemofor demo session minting) fails withPermission 'iam.serviceAccounts.signBlob' denied. Prod had been granted manually long ago; staging finally caught up. - Firestore export captured for both projects before the fixture
apply — rollback insurance for review week
(
gs://<bucket>/seed-rollback-2026-05-09/).
Session digest: docs/session-2026-05-09-review-week-hardening.md.
2026-05-08 — App Attest incident on TF Build 2
Real-device build TF2 hit App Attest with a cryptic INTERNAL
response. Two overlapping causes, both diagnosed via a JSON-spec
walker over the iOS Proof-of-Personhood chain:
APP_ATTEST_ENVenv var missing on the prodrecordMobileAttestationCloud Function (post-Rocket-retirement config drift).FUNCTIONS_ENV_PRODsecret reconstructed; a force-rebuild commit picked up the new value.- Artifact Registry
gcf-artifactsrepo had been wiped by an over-aggressive cleanup policy (tagState: ANY+ 7-day retention). Cloud Run revisions referenced now-deleted image digests. Policy reset totagState: UNTAGGED+ 30-day retention; runbook captured for re-application across new Firebase projects.
The diagnostic walker — scripts/monitor-flow.mjs driven by
poh.flow.json — checks the App Attest → email-link → ZK passport
→ Semaphore commit chain end-to-end with Cloud Functions trace +
Firestore assertions per step. Reusable for any future server-side
PoH regression.
2026-05-04 → 07 — No-Mac iOS CI + TF Build 4 (mobile)
Foundation Mobile shipped a complete CI pipeline that does not depend on a local Mac dev box:
- GitHub Actions
macos-15runners + Xcode Cloud orchestrate full archive → notarize → TestFlight uploads. - Apple App Store Connect API keys (rather than Apple-ID-tied certificates) so secret rotation runs entirely in Linux.
- TF Build 4 ships TF2 source — the canonical archive of commit
604002d(=v0.1.0=v0.1.1) plus 11 uncommitted files recovered from a Mac in repair. End-to-end iOS auth + sign-in verified on Build 4.
Pipeline detail + build inventory:
docs/build-history-2026-05-01.md,
docs/build-history-2026-04-28.md.
2026-05-01 → 03 — Partners-site polish (recovered via PR #56)
Three small UX fixes had been stuck in the stale-PRs queue (#25-#27) behind a 33k-line merge conflict. Cherry-picked onto a fresh branch and shipped on 2026-05-09:
- "Continue with Google" sign-in button on
partners.foundation-global.com+docs.foundation-global.comlogin pages. - Removed the 5-app icon strip from the sidebar (clutter; only one of the apps was clickable from an unauthenticated session anyway).
- Removed the "Deadline: May 4, 2026" countdown footer; the application deadline has long passed, so the countdown was disorienting for any post-deadline visitor.
April 2026 — Security hardening + go-to-market readiness
2026-04-20 — Security sprint
Focused six-commit push to close the gaps opened by the Rocket retirement and
the external review of the @plantagoai/* shared packages.
- App Check enforced on all 25 callables (
b997a66c) - Governance writes now validated client-and-server via Zod schemas (
5e4792ab), with a Phase 0 auth hotfix (9d8e23ca) in front - CSP widened narrowly for reCAPTCHA Enterprise (
52ee1cb4,a726374f) - Manual-review ID photos moved from Firestore to Cloud Storage (
ed6381bf) - PoH Phase 4: abuse registry + threat model + E2E coverage (
2f5ccd5b) - identity_proofs lockdown scaffolding + App Check opt-in (
4498a330)
Full write-up: docs/security-hardening-2026-04.md. Remediation backlog:
docs/security-fix-plan-2026-04-20.md.
2026-04-19 — Rocket retirement
The Rust evoting-rocket-server/ REST gateway is gone. A week of Phase 3 → 5
work collapsed three domains into Firebase Cloud Functions.
- PoH proxy collapsed (
d092f0eb) — Self Protocol ZK verification now direct inverifyPassportProof - Auth surface retired (
58846ed7) — Firebase Auth email-link invites replace the Rust gateway's auth routes - Solana-write client + access routes dropped (
2b6a0b4a) - Final deletion (
e3420e43) — ~22k LOC of Rust source + build scripts removed - WebAuthn/Rocket-era dead code swept (
6b2c0207) - Anchor Phase 2 shipped: 5 onCall Functions running the Solana write path
end-to-end (
d92d627b) - Phase 2 WIP — per-user Solana custody via KMS envelope encryption (
8ab4231e, blocked → unblocked ind92d627b)
See docs/architecture_backend-consolidation-2026-04-18.md for the current
backend architecture. Retired source: archive/rocket-retirement-2026-04-19/.
2026-04-18 — Phase 1 Cloud Functions Solana client + PoH tier derivation
- Phase 0: honest PoH tier derivation in
functions/lib/tier.js(95317930) - Phase 1: Cloud Functions Anchor client (
functions/lib/solana.js) plumbed with program deployment from fresh repo source scripts/sync-idl.shformalized as the single path for IDL sync
2026-04-15/16 — Shared-package adoption + architecture docs
@plantagoai/firebase-coreintegrated on the Foundation frontend (97db471a)@plantagoai/aiintegrated intoevaluateProposalfor Claude prompt caching (979cd9e7)@plantagoai/messagingpowering in-app notifications (7cd8ac6c)- Foundation Cloud Functions upgraded to
firebase-admin@13,firebase-functions@7, ESM (6e207150) - Architecture docs consolidated (
ca8467bf, +docs/architecture_wave3-2026-04-16.md,docs/architecture_components-2026-04-16_01-30.md)
2026-04-13 — Multi-tenant rollout + pillar rebrand
- Multi-tenant Phase 1 —
tenant_idfield, routing, data migration (8acd6d7e) - Multi-tenant Phase 2 — branding, admin panel, memberships (
17d0fb05) - Pillars rebranded: Your Voice / Your Share / Your Market (
08c23e13) - Branding sweep across docs, UI, tests (
7078946c) - Admin panel: Governance tab renamed to Workflows; date-range Reports filter
(
a0a666d4)
2026-04-11 → 12 — Proof-of-Humanity Phase 1 → 3
- Phase 1: Self Protocol ZK enrollment via
verifyPassportProof(e1b3d494) - Phase 1.5: identity_proofs locked to server-only writes (
6a641d82) - Phase 1.6: coverage matrix + mDL ISO 18013 type surface (
06406283) - Phase 2a: device-side Semaphore identity generation (
cfa25919) - Phase 2b:
attachSemaphoreCommitmentCloud Function (5e070712) - Phase 3: anonymous voting over Semaphore, manual-review fallback for docs
without MRZ (
bc9a098a) - Phase 3 follow-up: document-type selector + IL/PT copy, mDL documented
(
f834435f)
Core doc: docs/foundation_poh-2026-04-11_00-46.md. Country-specific status:
docs/poh-mdl-status.md, docs/zk_il_pt-20260414:0937.md.
March 2026 — Foundation + PoH Phase 0
Groundwork for the April sprint: multi-tenant plan, admin tools shipped, shared infrastructure framing solidified.
- DB Validator (Firestore schema + referential integrity + aggregate checks) across 11 collections, admin-panel UI
- Dynamic Action Items migrated from hardcoded arrays to Firestore-backed real-time CRUD
- Growth Strategy doc ($100 sign-up bonus, two-sided referrals, org partnerships) backed by PayPal / Robinhood / Dropbox / Nextdoor case studies
- Multi-Tenant Architecture plan: tenant_id → full isolation → self-service provisioning, three phases
- 3 new E2E Playwright specs (admin-tools, proposal-flow, api-health)
- PoH Phase 0 audit: realistic assessment of what passport flow actually
verifies (
docs/poh-phase0-audit.md)
See readme/CHANGELOG.md for the v14/v13 release notes in release format.
February 2026 — Initial shape
Foundation devnet-v6 branched from devnet-v5 with three axes of change:
- Move off the Node.js testing gateway into a compiled server tier (later retired — see April 2026 entries).
- Adopt Firebase Auth + Firestore as the primary user + data plane, leaving Solana as the verifiable-audit layer only.
- Bet on the three-pillar vision as the long-term thesis: one identity + governance engine, three product wedges.
The Rocket tier later got retired (April 2026) in favor of Cloud Functions — but the Firebase-primary decision survived and became the spine of the current architecture.
How this doc is maintained
- Append new entries at the top. Don't rewrite history unless correcting an error.
- Each major commit or architectural decision gets at least a 1-line mention with its SHA.
- When a phase completes, replace any "WIP/blocked" entries with the resolving commit so the timeline is accurate to current state.
- The partners site
/developmenttimeline view renders this file verbatim — keep it reader-first (no internal-only jargon, no "TODO: flesh out later").