Skip to content

CI-001C — Configure protected short-lived Firebase deployment identity #133

Open

Description

@daliu

Outcome

Give GitHub Actions a protected, short-lived, least-privilege identity for Firebase deployment. Prefer GitHub OpenID Connect plus Google Workload Identity Federation. Do not put a downloaded service-account key in the repository, website build, issue, email, screenshot, or AI conversation.

This is an owner/configuration ticket. It is not ready to claim until the owner confirms the target Firebase/GCP project, the staging project, the named release/recovery owner under #697, and the private place where IAM evidence will be kept.

Officer impact: The named owner can approve a backend release without handling or copying a long-lived cloud key.

Officer documentation: Update docs/officers/ACCESS_CONTINUITY.md, docs/officers/PUBLISH_AND_CHECK.md, and OPERATIONS_RUNBOOK.md with only the verified no-secret approval/revocation steps.

Deployment evidence: None at creation. No Firebase, website, provider, or production change is authorized by publishing this ticket.

Why this is atomic

This ticket establishes deployment identity and approval only. It does not deploy application code, Functions, Firestore Rules, indexes, or a website. CI-001D will use the approved identity for a controlled backend-first release.

Prerequisites / owner decisions

Required design

  1. Use a dedicated deploy principal; never a personal account or frontend identity.
  2. Trust only this repository and the approved workflow/environment/ref conditions.
  3. Issue short-lived credentials only after protected-environment approval.
  4. Separate staging and production authorization when the provider permits it.
  5. Grant only permissions required for the reviewed Firestore Rules and targeted Functions deployment. Do not grant project Owner/Editor as a shortcut.
  6. Keep runtime service identities separate from the deploy identity.
  7. Make missing/mismatched authority fail before any deployment attempt and leave the website unpublished.
  8. Redact project numbers, pool/provider IDs, service-account addresses, tokens, policy dumps, and private console links from public evidence.
  9. Document revocation, reviewer removal, repository transfer, and compromised-workflow response.

Acceptance criteria

  • Private inventory names the staging/target projects, deploy surfaces, runtime identities, deploy identity, and approved owners.
  • GitHub environment approval is required and tested with a made-up no-op or read-only staging check.
  • OIDC/WIF trust is restricted to the exact repository and approved environment/ref.
  • No long-lived cloud credential is stored in GitHub, Netlify, source, build output, logs, or officer instructions.
  • Missing authority, wrong repository/ref/environment, and unapproved production attempts fail closed.
  • Credential/token output is masked and no provider identifiers are copied into public comments.
  • Dave can revoke access using the private continuity record; no backup recovery coverage is claimed.
  • IAM review records why each permission is necessary and confirms no project Owner/Editor shortcut.
  • Source/docs changes, provider configuration, staging proof, and production authorization are reported as separate states.
  • CI-001 — Establish trustworthy quality gates and protected deployment #105 links this child and CI-001D remains blocked until this issue closes.

Stop conditions

Stop if a step requests a JSON key, token, password, recovery code, project policy dump, private link, or broad Owner/Editor role in a public place. Stop if the exact target project or named approvers are unknown. Escalate to the platform/security owner and cloud IAM specialist.

Claim protocol

Creation is not a claim. After owner prerequisites are recorded privately, assign one agent, post CLAIMED by <canonical agent> at <UTC>; branch <branch>, and change the label only when the ticket is actually dependency-clear. Provider-console work requires the named human owner present; an agent must not invent or copy secrets.

Superseding backend ownership decision — October 11, 2026

Direct human owner instruction: continue without a backup owner. #697 records Dave Liu (daliu) as sole backend release/recovery owner. Backup-appointment/two-owner requirements in this ticket no longer gate backend setup; backup coverage remains absent. Existing staging read-only reviewers gain no broader authority. All other scope, data/policy, protected-release, least-privilege, staging, exact-source and rollback requirements remain unchanged. This amendment does not complete this issue or authorize a skipped/partial release.

Activity

  1. added
    priority:P0Launch blocker or urgent security risk
    type:securitySecurity or privacy boundary
    area:firebaseFirebase services and data
    area:ciContinuous integration and deployment
    size:MMedium multi-file issue
    needs-external-configRequires provider console or external configuration
    on Jul 13, 2026
  2. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    Fail-closed production release evidence (no provider identifiers or secret values)

    For exact merged main 46557c7, protected release run 29247125844 passed current-main and exact-CI preflight. It stopped at public website configuration because the required App Check site-key variable is absent.

    The website artifact was not built. Cloud authentication did not run. Firebase deploy/readback and GitHub Pages publication were skipped. The production environment is not present in GitHub environment metadata, and no release variable/secret names are currently listed at repository scope. No values were requested, read, printed, or changed.

    This preserves the ticket blocker: named owner/IAM decisions, protected environments, public build configuration, and short-lived authority still need private setup and verification. Do not bypass this with a JSON key or broad role.

  3. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    Read-only deployment audit after CONFIG-001A #149 merged as 2c62b8d: repository Actions has no required public build variables/secrets, only the existing github-pages environment, and no production protected environment to supply reviewed authority. No values were requested or printed. No deployment was triggered. The current protected workflow also supports only profile-recovery, not the #149 commerce/mail Function set. Owner action remains: create/review protected production configuration and short-lived identity privately, then add a separate immutable Function plan through review.

  4. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    CONFIG-001B1/#151 merged as 7c7a41c with exact post-merge CI 29250935019 green. It remains source-only. Current protected release exposes only profile-recovery, and production preparation previously failed closed because the required public App Check key was absent. Do not represent #151 as deployed until a reviewed fixed release plan, protected environment authority, runtime controls, and exact readback exist.

  5. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    Read-only release-gate evidence at 2026-07-13T13:08:36Z: protected production run 29252492614 for exact commit 23bca8c passed current-main/CI validation but stopped before cloud authority because the required public App Check site key was absent.

    The Firebase identity/WIF deployment step was skipped, so #133 authority and IAM remain unverified. No secret or credential was added, printed, or inferred.

  6. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    Read-only App Check release audit — updated 2026-07-13

    Protected release 29254280177 targeted exact main 594306fb06d9a6a2a44b5675b305f462f11b877d. Its exact-main and exact-CI preflight passed. It then failed closed at the first website configuration check because REACT_APP_RECAPTCHA_SITE_KEY resolved empty.

    No checkout, website build, artifact upload, Firebase deployment, or Pages publication ran in that release. This is source/CI evidence only; no website, Firebase, provider, or production behavior changed.

    A redacted repository-settings audit found no repository Actions variables or secrets and only the existing github-pages environment. The workflow job that prepares the website is not currently bound to a protected staging/production environment, so under the current source the public App Check key must come from a repository or organization Actions variable. Do not add a placeholder or bypass the guard.

    At the audited release commit, the client instantiated reCAPTCHA v3 while the authoritative security design required Enterprise. Source-only child #159 corrected that mismatch and merged through PR #160 as exact main 317b800cd39af136828de0d4eb23fbef66c2b390; post-merge CI 29259342966 passed. Netlify production attempt 6a54fa22230b8000085802ec for that exact merge ended in error with no published timestamp, and runmprc.com remains on older verified commit e86a0f702cff6495f50630c5de3337290db8b8cb. No protected release, Firebase deploy, GitHub Pages run, provider configuration, callable enforcement, or live attestation occurred.

    Safe remaining sequence:

    1. Confirm the approved Firebase project/host inventory under BACKEND-001 — Audit the Firebase cutover and approve legacy data disposition #113.
    2. Keep the merged Enterprise source/tests from ABUSE-001A1 — Use reCAPTCHA Enterprise for browser App Check #159.
    3. Have the named owner create the approved staging/production Enterprise site key and allowed-domain policy.
    4. Bind website preparation to the approved protected Actions scope under CI-001C — Configure protected short-lived Firebase deployment identity #133/a dedicated CI child, then store only that public site key there. Never place server credentials in a public build variable.
    5. Complete protected environment and least-privilege deployment authority under CI-001C — Configure protected short-lived Firebase deployment identity #133.
    6. Rehearse the exact revision in staging, verify App Check metrics/allow-deny behavior, then publish and verify each website/Firebase/provider surface under CI-001D — Prove backend-first staging and deploy the profile repair #136 and ABUSE-001A2.

    This comment contains no key value, secret, private locator, or production data.

  7. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    A fresh read-only release audit is recorded on #136. No protected production environment or repository-scoped short-lived Firebase deployment configuration is currently visible. Organization inheritance was not auditable with this token. Provider/IAM setup remains owner action; no credential, secret, or cloud setting was changed.

  8. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    REDACTED READ-ONLY CONFIGURATION AUDIT — 2026-07-13T23:30:08Z

    The repository currently has no GitHub environment named production; only the Pages environment is visible. The repository-level public App Check key variable, target-project variable, and short-lived deploy-authority configuration expected by the protected workflow are also absent. Organization-level variable visibility was unavailable, so no claim is made about organization configuration.

    Protected release run 29293185980 therefore failed closed at the missing public App Check key before checkout/build. Firebase authentication/deployment and Pages publication were skipped. A missing GitHub environment must not be treated as approval: dispatching a job that references a nonexistent environment can create an unprotected environment rather than supply the two-reviewer protection required here.

    No issue claim or provider change was made. #133 remains blocked on the private estate decision, named reviewers/recovery owners, real protected staging/production environments, and least-privilege WIF/IAM configuration. Provider identifiers and private evidence must remain outside public comments.

  9. daliu commented on Aug 1, 2026

    @daliu
    ContributorAuthor

    REDACTED CURRENT CONFIGURATION AUDIT — 2026-08-01T18:41Z

    This read-only audit supersedes the older statement that no production environment exists. GitHub now returns an environment named production, but it has zero protection rules, no deployment branch policy, administrator bypass enabled, zero environment variables, and zero environment secrets. No staging environment exists. Repository Actions exposes zero repository variables and zero repository secrets; organization inheritance remains unauditable with this identity.

    The committed release workflow still requires FIREBASE_PROJECT_ID, REACT_APP_RECAPTCHA_SITE_KEY, GCP_WORKLOAD_IDENTITY_PROVIDER, and GCP_DEPLOY_SERVICE_ACCOUNT, but none is available in the visible scopes. Its only release plan remains profile-recovery; it cannot release the directory feature. A local read-only Firebase Function-list request returned only a generic provider failure, so there is no provider readback proving deployment authority or live directory Functions.

    No environment, reviewer, branch rule, variable, secret, cloud identity, provider setting, workflow run, website, Firebase resource, or production data was changed. Do not treat the environment name as protection, dispatch into it, store a JSON key, or enable administrator bypass as a release shortcut.

    Owner actions remain: privately approve the exact staging/production estate; name two release reviewers and two recovery owners; create genuinely protected staging and production environments with no administrator bypass; configure repository-and-environment-constrained least-privilege OIDC/WIF; and prove no-op/read-only staging denial/approval paths before any backend release.

    Officer impact: No officer has a protected no-secret Firebase release path yet.

    Officer documentation: None changed by this audit; current guides correctly say protected release is not available.

    Deployment evidence: GitHub configuration read only; no release dispatched; Netlify, runmprc.com, Firebase, and outside providers unchanged.

  10. daliu commented on Aug 14, 2026

    @daliu
    ContributorAuthor

    PRE-CLAIM disjointness notice for #657, WEB-UX-004 — Move focus to main content after SPA path navigation.

    Exact proposed base is main 3265a55cb92df1ebb5401f2647ff81e4ca3af0b8, tree 322468cc75a57f7ea392eb9f57a201fb11c4b35a. Proposed ownership is exactly four paths: src/components/ScrollToTop.jsx only a pathname-bound, cancelable, one-shot main-focus settlement while preserving its scroll effect; src/App.jsx only the existing main landmark's stable target relationship and tabIndex={-1}; existing src/App.test.jsx only one separately named WEB-UX-004 generated focus/race matrix and real-shell proof; and docs/officers/PUBLISH_AND_CHECK.md only one separately named no-terminal route-focus verification procedure adjacent to the historical #291 keyboard procedure.

    There is no new test file, lint-baseline change, CSS change, root-document change, Navbar/Footer/route-page change, backend/service/Rules/Functions/index/package/workflow change, provider/account/sign-in/data action, deployment/publication action, or live claim. Released #291 visible-focus/skip-link behavior and #490 mobile disclosure/close behavior remain immutable. #504 stays the disconnected directory coordinator, #507 retains every future connection/release gate, and availability stays byte-for-byte literal false. #616 retains both Strava Function paths and its separate OAUTH/RISK-024 SECURITY hunk. #133/#136/#460 retain their separate future publication procedures; this new guide hunk is separately named.

    Issue creation is not a claim. No source or documentation edit has been made. Send STOP only for an exact path/hunk collision or dependency; otherwise no reply is required. The exact issue/claim/open-PR state will be reread immediately before editing.

  11. daliu commented on Aug 14, 2026

    @daliu
    ContributorAuthor

    PRE-CLAIM coordination for #659 / WEB-002D. This issue uses the existing reviewed one-shot Netlify manifest/build control to publish one exact frozen web artifact, with rollback and immediate repause. It does not generalize reusable hosting, alter .github/workflows/deploy.yml, Firebase deployment, GitHub Pages authority, DNS, secrets, provider configuration, or close #460/#133/#136. Those issues retain their automation/ownership outcomes. Send STOP for an exact release-control collision.

  12. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    Focused staging-only child #667 is claimed. It establishes exact-repository/environment/ref OIDC/WIF authority and a protected read-only proof without deploying backend code, enabling billing, or changing production. #133 remains open for production authority and full continuity closure.

  13. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    CI-001C1 child #667 is complete through PR #668 and merge ee16bd16220ab58bd3a2add80dd2f39a1d514dd7.

    Staging now has an exact-main, two-reviewer, keyless GitHub OIDC identity proof. Protected run 33006732455 succeeded; wrong-ref run 33006901957 failed with zero steps before OIDC. The service account has zero user-managed keys and only resourcemanager.projects.get.

    Parent #133 remains open. Still missing: reviewed staging Firebase deployment roles, protected production environment/identity, and actual staged/production release evidence. No backend, billing, provider sandbox, website, or production change occurred.

  14. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    Next sequential child #669 is claimed for the empty staging Firestore substrate and exact Rules/indexes only. It uses current club-owner authority for one-time provisioning; it does not expand the #667 read-only service account or claim that protected deployment roles are complete.

  15. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    CI-001D1 child #669 is complete through merged PR #670 (044fc9b624334d7e560d9ee6d9d4a70fb5fe0411). Exact tested Rules and indexes are active on the empty run-mprc-staging Firestore database, all index definitions are READY, three fixed anonymous server-only probes deny, and root collection count is zero.

    This does not broaden #667's read-only identity and does not satisfy #133's remaining work. The keyless Firebase deployment roles, protected production environment/identity, and complete release authority are still NOT AVAILABLE YET. Full evidence: #669.

  16. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    Child #671 will use the established club-account short-lived token pattern for a narrow staging Auth-only deployment after exact source reaches main. It does not grant deploy roles, create keys, or mutate production.

  17. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    Staging source-hardening milestone: child #674 completed through merged PR #675 at 4b8ed83. Exact-main CI run 33016096438 passed all five required jobs. The repository now has an argument-closed wrapper for only the paired profile Functions in run-mprc-staging.

    This grants no IAM or deploy authority. The #667 keyless principal remains project-read-only; zero relevant Function service APIs are enabled; billing remains false; the club account sees zero open billing accounts; and no Function was deployed. Parent #133 remains open for reviewed least-privilege deployment roles and production protection.

  18. daliu commented on Oct 11, 2026

    @daliu
    ContributorAuthor

    Owner-gate readback — 2026-10-11 UTC

    Fresh non-mutating check at main 81ea6d9:

    • staging has two individual required reviewers: daliu and jeffchang5; custom deployment-branch policy enabled. Self-review prevention is off and administrator bypass is allowed. Existing reviewer presence is not broader deployment/recovery authorization.
    • production exists but has zero required reviewers and no deployment-branch policy; administrator bypass allowed. Protected production approval is therefore not configured.
    • BACKEND-001 — Audit the Firebase cutover and approve legacy data disposition #113 remains OPEN with partial configuration evidence, not approved source disposition. CI-001D — Prove backend-first staging and deploy the profile repair #136 remains OPEN and explicitly stops while its dependencies are open.
    • No new backup deployment/recovery owner approval is recorded. Owner prerequisites in this issue remain unsatisfied; this check is not a claim or permission to grant roles/change protections.

    The previous billing-disabled staging observations are historical: #693 now verifies the existing trial-linked staging account and alerts-only warning budget. This removes that billing prerequisite only, not release authority.

    Officer impact: backend release remains unavailable; no officer action or transaction became live.
    Officer documentation: current access-continuity guide unchanged; dated private redacted owner-gate handoff records this check.
    Deployment evidence: GitHub protection metadata read only; no GitHub settings, cloud IAM/API, Firebase, website, payment or member-data mutation. No hosted workflow dispatched.

  19. daliu commented on Oct 11, 2026

    @daliu
    ContributorAuthor

    October 11 next authority boundary (read-only review)

    #697 is complete through merged PR #698 (3d09085). Production GitHub approval metadata reads back daliu only, main-only branch policy, administrator bypass disabled, and self-approval allowed. Existing staging read-only environment/principal/reviewers were not broadened. Cloud deployment authority is not yet established.

    Staging service-account/project-policy metadata shows no default first-generation runtime identity and no direct service-account Owner/Editor grant. Source profile Functions currently have no explicit runtime serviceAccount. ensureMemberProfile needs Auth users.get and Firestore profile transaction permissions; signup needs profile transaction permissions, not claim updates. The next bounded implementation must review explicit runtime/build/deploy identities and minimum roles against the pinned Firebase CLI's first-generation path. Do not invent a default or grant Owner/Editor.

    Keep a separate staging backend environment and dedicated deploy trust rather than reusing #667's five-minute project-get-only identity. Bind exact repository/immutable owner and repository IDs/main/workflow/environment. The current general release intentionally rejects staging before authentication and later unconditionally downloads a production Pages artifact; a reviewed staging path and negative tests are needed, not only provider IAM. Preserve the two-profile-Function target allowlist, native App Check, minInstances zero/maxInstances two, exact source and backend-first rollback checks.

    Officer impact: No new backend approval or deployment procedure is available yet. No further officer identity is required.
    Officer documentation: PR #698 updates scoped continuity/publish guidance; broader backend release remains NOT AVAILABLE YET.
    Deployment evidence: GitHub approval configuration and read-only provider metadata only. No cloud IAM/API/billing/runtime, member data, website or payment change. #133 remains open.

  20. daliu commented on Oct 11, 2026

    @daliu
    ContributorAuthor

    Scoped staging authority child complete

    #699 completed via PR #700, merge ce7102b, with six green PR/main jobs and protected no-op run 38173389908 approved by daliu. A separate staging-only keyless principal/custom 26-permission role/trust is active; zero user-managed keys, no runtime/build actAs or direct account/data/secret privileges, no production project binding. Original #667 read-only authority/Jeff permissions unchanged. Administrator bypass restored at owner request; the proof used normal named approval, not bypass.

    This completes only the narrow engineering authority child. #133 remains OPEN for runtime/build separation, the actual fixed-target staging deployment path, full negative/revocation/recovery proof and production authorization. #113/#136 and broader core operation remain OPEN. No Firebase runtime, Rules, website, payment, member data, API enablement or paid upgrade occurred.

    Officer impact: An engineering identity check is verified, not a usable member backend.
    Officer documentation: PR #700 access/publish/entry/runbook/security/status guides and conditional acceptance record.
    Deployment evidence: GitHub/staging IAM and protected read-only verification; no application deployment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:ciContinuous integration and deploymentarea:firebaseFirebase services and dataneeds-external-configRequires provider console or external configurationpriority:P0Launch blocker or urgent security risksize:MMedium multi-file issuestatus:blocked-ownerRequires an owner or external decisiontype:operationsOperational setup or runbooktype:securitySecurity or privacy boundary

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions