Repository navigation
CI-001B2 — Make releases protected, backend-first, and fail-closed #135
Description
Outcome
Replace the current automatic, frontend-first, fail-open release workflow with a release gate that cannot publish a dependent website before its compatible backend. Remove every server credential from the frontend build job and make missing authority/config an explicit failure.
This ticket changes release behavior and is blocked on an owner choice before source edits:
- Recommended: merges run CI only; staging/production releases are manual, protected, exact-commit actions.
- Alternative:
mainautomatically deploys to isolated staging, while production remains a protected manual action.
Do not preserve today's “merge automatically publishes production Pages” behavior for backend-dependent changes; it cannot satisfy backend-first approval.
Officer impact: Officers will approve a merge separately from a protected release, and a missing backend credential will be shown as a stopped release rather than a green success.
Officer documentation: Update OFFICER_START_HERE.md, docs/officers/PUBLISH_AND_CHECK.md, docs/officers/ACCESS_CONTINUITY.md, and the exact root release-status docs after the owner selects the release model.
Deployment evidence: None at creation. This ticket changes the gate only; CI-001D performs and proves the staged/live release.
Current verified defect
.github/workflows/deploy.yml currently:
- runs on every
mainpush; - publishes GitHub Pages before the Firebase job;
- passes
FIREBASE_SERVICE_ACCOUNTinto the frontend build environment; - installs
firebase-tools@latestover the network during deployment instead of using the lockfile version; - deploys all Functions, Rules, and indexes rather than an approved target set;
- reports success when
FIREBASE_SERVICE_ACCOUNTis missing and Firebase is skipped.
That workflow cannot safely release PR #132/#118.
Atomic source outcome after owner decision
- Separate merge/CI from release authorization.
- Require an exact merged commit and its required checks before release.
- Validate environment, target project, approved deploy scope, and authority before any mutable install, build, or publication.
- Use the lockfile-pinned Firebase CLI; do not install
latestduring release. - Give the frontend build only public browser configuration. Never pass a cloud service credential or write a key file in that job.
- Make the backend job complete and verify first; the website job must depend on its success.
- Use fixed reviewed deployment targets rather than caller-supplied shell text or a broad all-Functions default.
- Make missing/mismatched authority, skipped backend, wrong ref, or partial verification fail the workflow and prevent website publication.
- Give jobs minimum GitHub permissions; CI-001C supplies the approved short-lived cloud identity.
- Keep staging and production evidence distinct.
Acceptance criteria
- Dave/board records the selected release model and names production approvers.
- A normal merge cannot silently publish a backend-dependent production website.
- No server credential exists in the frontend environment, build files, artifacts, or logs.
- Backend verification is a hard prerequisite of website publication.
- Missing authority/config fails before deployment and cannot end in an overall green “skipped” release.
- Firebase CLI/version comes from the committed lockfile.
- Deployment targets are fixed, reviewed, and shell-injection safe.
- A temporary synthetic missing-authority probe fails and publishes nothing, then is removed.
- Workflow YAML/static checks, CI, and affected officer procedures pass independent review.
- CI-001C provider configuration and CI-001D actual deployment remain separate.
Stop conditions
Stop if the owner has not chosen the release model, if an implementation needs a cloud key in source/frontend, if it accepts arbitrary deployment targets, or if it can publish the website after a failed/skipped backend. Do not deploy from this ticket.
Claim protocol
Creation is not a claim. After the owner decision, publish the exact allowed files, assign one agent, and post CLAIMED by <canonical agent> at <UTC>; branch <branch> before editing. Coordinate root-document ownership with PR #132/#118; do not overwrite its profile-recovery sections.
Activity
daliu commentedon Jul 13, 2026
OWNER DECISION / CLAIM at 2026-07-13T08:54:57Z:
Dave authorized agents to push, merge, and deploy and directed the queue to proceed one issue at a time. The selected release model is the recommended option: normal merges run CI only; staging and production releases are separate manual, exact-commit, protected actions. Production still requires the environment's named human approval and the short-lived authority owned by #133; this authorization does not invent credentials or provider configuration.
CLAIMED by
/rootat 2026-07-13T08:54:57Z; branchcodex/issue-135-protected-releases.Initial exclusive source scope:
.github/workflows/deploy.ymlOFFICER_START_HERE.mdOFFICER_HANDBOOK.mddocs/officers/README.mddocs/officers/PUBLISH_AND_CHECK.mddocs/officers/ACCESS_CONTINUITY.mdPR #132/#118 retains
SECURITY.md,OPERATIONS_RUNBOOK.md, profile/runtime/Rules tests, and its officer profile sections. #134 retains only its declared Sentry files. I will post a scope amendment before touching any additional path. This ticket changes and tests the gate; it will not perform a Firebase or website deployment.daliu commentedon Jul 13, 2026
SCOPE AMENDMENT at 2026-07-13T09:02:44Z after read-only release-boundary review:
The live custom domain is served by Netlify, and its Git connection currently creates production deploys from
main. Editing the GitHub workflow alone would therefore leave a second automatic publication path. #135 now also owns the smallest repository-controlled containment: a testednetlify.tomlignore command that stops Git-triggered production builds while leaving deploy previews available for public, read-only review. Netlify build hooks/provider settings and a protected Netlify publication path remain WEB-001/provider work; #135 will not claim that the GitHub release publishesrunmprc.com.Additional exclusive source/test paths:
.github/workflows/ci.yml(one hosted release-gate test step only)netlify.tomlscripts/netlify-ignore-build.jstests/release-workflow.test.jsAdditional exact truth/diagram hunks:
README.mdAGENTS.mdIMPLEMENTATION_PLAN.mdOPERATIONS_RUNBOOK.mdSECURITY.mdGITHUB_ISSUES.mdGITHUB_ISSUE_SLICES.mddocs/officers/REQUEST_A_CHANGE.mddocs/officers/EVENTS_SHOP_MEMBERS.mddocs/officers/SYSTEM_MAPS.mdThe original six officer paths remain owned. These documentation edits are limited to the #135 release state; they do not claim profile, email, events, monitoring, payment, data, or hosting-cutover behavior.
PR #132/#118 keeps all runtime/Rules/tests and profile/App Check content. #135 temporarily owns only the release-status paragraphs in
SECURITY.mdandOPERATIONS_RUNBOOK.md; #118 will refresh after #135 and preserve them. #134 remains limited to its declared Sentry files.Invariant: normal GitHub merges run checks only on the GitHub-controlled path, Netlify Git-triggered production builds stop, missing release authority fails red before installs/deploy/build/publication, Firebase is verified before any GitHub Pages publication, and
runmprc.comremains separately NOT AVAILABLE for protected publication until WEB-001/provider work is proven.daliu commentedon Jul 13, 2026
SECOND SCOPE AMENDMENT at 2026-07-13T09:10:36Z after independent workflow threat-model review:
Additional owned paths:
.gitignore— ignore onlygha-creds-*.json, as required by the pinned Google auth action.github/scripts/verify-firebase-release.mjs— redacted provider readback for the exact Rules source and both Function revisionstests/firebase-release-verification.test.js— pure fixture tests for positive and stale/mismatched provider stateThe workflow will also be tightened in its already-owned file: current-main only; exact successful
ci.ymlmain-push run/jobs; frontend artifact built before backend mutation; install/source validation before cloud auth; one fixed backend deploy command; always-run post-attempt readback; staging unavailable until an exact approved project is added by reviewed source change; provider identifiers sourced from protected environment secrets rather than visible variables.No provider call runs in this issue. The verification script is tested with made-up fixtures only. #133/#136 still own configured authority and actual provider readback/deployment.
daliu commentedon Jul 13, 2026
EXTERNAL STATE at 2026-07-13T09:16:16Z: changed the repository default branch from legacy dev to canonical protected main. This is required for the manual workflow to be discoverable/runnable from its reviewed main definition. No commit, website, Firebase, Netlify, or provider deployment was triggered. The legacy dev branch still exists and was not deleted.
daliu commentedon Jul 13, 2026
DESIGN CLARIFICATION at 2026-07-13T09:24:39Z after the independent trust-boundary review:
The earlier scope note said missing authority would stop before any build. The safer final order deliberately prepares the public, credential-free website artifact before backend mutation, so a later dependency/build failure cannot leave Firebase changed while the Pages artifact is unavailable. That preparation has read-only source access, no environment binding, no cloud identity, and no publication permission.
Missing protected configuration still fails before backend dependency installation, cloud authentication, provider access, deployment, or website publication. The prebuilt artifact remains unpublished and expires. This clarifies “mutable build” in the issue as an externally mutable/provider-capable step; it does not weaken the hard acceptance rule that missing authority or failed/partial Firebase verification publishes nothing.
PR #138 and the officer diagrams now state this exact boundary. No release or provider call was run.
daliu commentedon Jul 13, 2026
THIRD SCOPE AMENDMENT at 2026-07-13T09:38:16Z after exact provider/readback review:
GitHub Pages currently reports
runmprc.comas its custom domain, and the normal GitHub Pages URL redirects to that name, while public DNS serves Netlify. Calling it a separately reachable copy would be false and continuing to publish a CNAME would perpetuate competing ownership.Additional owned paths:
public/CNAME— remove the future artifact's stale Netlify-domain claimSYSTEM_DESIGN.md— replace the obsolete automatic/green-skip system flow with the exact protected release and current CNAME conflictdocs/officers/GLOSSARY.md— correct the one-line Pages definitionThis is source containment only. Merging PR #138 does not publish Pages or change the current provider setting/DNS. #136 plus a protected Netlify child under WEB-001 must publish/read back the Pages branch without the CNAME and separately prove
runmprc.com. The new tests statically forbid a Pages CNAME. No provider or website action was run by this amendment.daliu commentedon Jul 13, 2026
COMPLETED — source gate and negative deployment proof (2026-07-13T09:55Z)
mainas9eafab1217aff7058c42240aaba72d7b93f8ed24; exact source head4da12d6f3dea8559a2d30a0453dd1c20c2c758achad two independent approvals.Required protected cloud authority is missing.github-pagesenvironment.68b823a5f2a42e0490859dc74e5188d89fd5181c; neither the merge nor either probe published Pages.Officer impact: a merge now changes source and runs checks only. A release is a separate exact-commit request, and missing configuration or authority is a visible red stop before backend or website publication.
Officer documentation: merged in #138 across the root handbooks/system maps and the affected short officer guides.
Deployment evidence: source gate live; negative fail-closed behavior proven. No production application deployment is claimed by this issue.
CLAIM RELEASED at
9eafab1217aff7058c42240aaba72d7b93f8ed24.