Repository navigation
docs(governance): add code freeze policy for TeachLink Backend (#1840) - #1919
Merged
RUKAYAT-CODER merged 1 commit intoOct 17, 2026
Conversation
…code#1840) Add Governance/policies/CODE_FREEZE.md: the versioned reference for code freezes that the Governance folder was missing. It defines when a freeze applies (release stabilization, release sign-off, security embargo, incident, error-budget exhaustion, scheduled maintenance) and how one is declared and ended, what is allowed and prohibited during a freeze, the exception process (who approves, how to request, decision timelines, recording and expiry), enforcement, roles, and regression-test guidance. Record the addition in Governance/CHANGELOG.md. Scope is deliberately two files, both inside Governance/, per issue rinafcode#1840; no application code, configuration, schema, or dependency is touched. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
|
@eriifeomoniyi-hue Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
9 tasks done
Contributor
|
Thank you for contributing to the project |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add a code freeze policy for TeachLink Backend
Closes #1840
Governance/TL;DR
Issue #1840 identified a governance gap: the
Governance/tree had versioned policiesfor release branching, branch protection, approval requirements, backports, review
SLAs, and embargoes — but no document defining a code freeze. This PR adds
Governance/policies/CODE_FREEZE.md, the single versioned reference that answersthree questions contributors and maintainers were previously answering ad hoc:
when does a freeze apply, what may still land during one, and how is an exception
granted? The addition is recorded in
Governance/CHANGELOG.md. Exactly two fileschange, both inside
Governance/.1. Motivation and background
Governance/policies/CODE_FREEZE.mddid not exist. The only mention ofa freeze anywhere in the governance tree was a dangling passing reference in
Governance/policies/COMMUNICATION_NORMS.md§4.3 — "Pull requests targetingmainduring a release freeze" — which pointed at no definition, no declaration procedure,
and no exception path.
release/x.y.zbranches (RELEASE_BRANCHING.md), gates merges behind sign-offs(
processes/RELEASE_SIGNOFF.md), freezes non-remediation deployments when an errorbudget is exhausted (
domains/SLA_SLO.md), and holds branches during securityembargoes (
EMBARGO.md). Without a freeze policy, each of those moments producedinconsistent expectations: contributors didn't know whether to open PRs, reviewers
didn't know what to accept, and there was no defined way to grant an exception or a
record when one was granted.
the
Governance/folder, with a maximum scope of two files.2. What a code freeze means in this policy
Two design invariants underpin the whole document:
announcement naming scope, reason, trigger, start, expected end (or ending event),
approver, and owner — posted as a pinned GitHub issue, echoed on open PRs, and
mirrored to the community channels in
COMMUNICATION_NORMS.md. This makes freezestatus discoverable rather than folklore.
and approval from
APPROVAL_REQUIREMENTS.md§2. Freezes restrict what lands; theydo not relax how it is reviewed, and they never authorise bypassing branch
protection.
3. Contents of
Governance/policies/CODE_FREEZE.mdMetadata header (Status
Active· Version1.0.0· OwnerMaintainer Team, with the release manager· Last reviewed2026-10-17· Review cadence every 6 months ·applies-to plus a Related row linking ten sibling documents), then:
release/x.y.z→ tag onmain), release sign-off (start of gates → recorded decision), security embargo (perEMBARGO.md), incident/degraded service (declaration → all-clear), error-budget exhaustion (perdomains/SLA_SLO.md/MIGRATION_ROLLBACK.md), scheduled maintenance — each with declaring role and default window. §1.2 declaration lifecycle: who may declare, mandatory declaration contents, announcement channels, retroactive effect on already-open PRs, amendments/extensions, and the rule that normal merging resumes only after the freeze is formally lifted.VULN_SLA.md+EMBARGO.md), release-blocking fixes, documentation & comments, change-record updates (release notes, changelog, decision log), reverts, and CI/tooling hotfixes needed to keep required checks green. §2.2 prohibited list: features, refactoring/"while-I-were-here" cleanups, dependency bumps (security exempt), unnecessary schema/migration work, protection-rule edits, force-push/deletion of branches, and any merge that bypasses required checks or approvals. §2.3 conditions for every landing change: the PR names its freeze trigger and justification, all required checks/approvals still apply, the diff is the smallest that satisfies the purpose, the merge strategy perMERGE_STRATEGY.mdis used, and the freeze owner/release manager performs the merge — plus the review-SLA carve-out delegated toCOMMUNICATION_NORMS.md§4.3 (acknowledgement within one business day by the freeze owner).processes/RELEASE_SIGNOFF.md§4); incident → incident commander and a maintainer; routine feature/cleanup → two maintainers including the freeze owner; embargoed security fixes → route throughEMBARGO.mdwith no separate exception needed; repository-wide/indefinite → lead maintainer. Self-approval only when no independent approver exists, and then it must be re-reviewed. §3.2 required request contents (PR link, trigger & scope, category + cost of delay, risk/rollback/verification, requested approvers). §3.3 decision rules: 1 business day (4 hours for incident-driven), approval recorded with approver/rationale/limits, denials state what would make it approvable later, approvals are single-PR-scoped never categorical. §3.4 recording inDECISION_LOG.mdwithin 24 h (mirroringAPPROVAL_REQUIREMENTS.md§5.3), expiry at freeze end or stated expiry (landed changes are not rolled back on expiry), disputes viaprocesses/ESCALATION_PATH.mdto the lead maintainer.freeze: exceptionlabel fromLABEL_TAXONOMY.mdmarks approved exceptions; non-compliant merges are reverted or handled as override violations underAPPROVAL_REQUIREMENTS.md§5 and noted in the decision log; backports defer toBACKPORT.md(eligibility §3).4. Design decisions and rationale
CODE_FREEZE.mdrather than amendingRELEASE_BRANCHING.mdBRANCH_PROTECTION.md("Overrides… may not disable branch protection rules") andAPPROVAL_REQUIREMENTS.md§5.2. A freeze that weakened review would trade one risk (unstable release) for another (unreviewed code).DECISION_LOG.mdwithin 24 hAPPROVAL_REQUIREMENTS.md§5.3) so emergency overrides and freeze exceptions appear in one audit trail.Governance/-only constraint rules out workflow edits; branch protection already blocks force-pushes, direct pushes and missing approvals, which is the enforcement a freeze actually needs on day one.5. Relationship to existing governance documents
policies/RELEASE_BRANCHING.mdmain/develop/release/*model, cut/stabilize stepsprocesses/RELEASE_SIGNOFF.mdpolicies/BRANCH_PROTECTION.mdpolicies/APPROVAL_REQUIREMENTS.mdpolicies/EMBARGO.mdpolicies/VULN_SLA.mdpolicies/BACKPORT.md/policies/MERGE_STRATEGY.mdpolicies/COMMUNICATION_NORMS.md§4.3domains/SLA_SLO.md,domains/MIGRATION_ROLLBACK.mddomains/ENV_PROMOTION.mdDECISION_LOG.mdLABEL_TAXONOMY.mdfreeze: exceptionlabel (§4)roles/RELEASE_MANAGER.mdprocesses/ESCALATION_PATH.md6. Alternatives considered (and rejected)
RELEASE_BRANCHING.mdwith a short freeze section — rejected: leavesincident/embargo/maintenance freezes undocumented, and issue Add a code freeze policy for TeachLink Backend #1840 explicitly asked
for
Governance/policies/CODE_FREEZE.md.CONTRIBUTING.md— rejected:Governance/README.mdreservesCONTRIBUTING.mdfor contribution mechanics; freeze semantics are governancepolicy, and touching
CONTRIBUTING.mdwould break the "Governance/only"constraint anyway.
rejected for this PR: it would require changes outside
Governance/. §6 insteadpre-specifies the regression tests any future automation must ship with, so the
policy and its eventual implementation stay in lockstep.
would technically create the file while leaving contributors no better informed;
the issue asks for a document that "documents when freezes apply / specifies what
is allowed / defines the exception process", so all three are written out.
7. Files changed (scope = 2, all inside
Governance/)Governance/policies/CODE_FREEZE.mdGovernance/CHANGELOG.md## [Unreleased] → ### Added, citing issue #1840git diff main --stat→2 files changed, 236 insertions(+), working tree clean, zero paths outsideGovernance/. (Thepnpm-lock.yamlchurn produced by dependency installationduring CI reproduction was reverted before staging and is not part of this branch.)
8. Acceptance criteria → evidence
git diff main --stat: exactly 2 filesGovernance/Governance/CHANGELOG.md,Governance/policies/CODE_FREEZE.mdonly;git status --porcelaincleanGovernance/is outside the Jest root (jest.config.js→rootDir: 'src'), outside the TS build (tsconfig.build.jsoncompilessrc/), excluded by.dockerignore's*.mdrule, and invisible to the CI build-artifacts guard@commitlint/config-conventional, doc style matches sibling policies (`Governance/CHANGELOG.mdentry + §7 of the policy, both citing #18409. Local CI verification (same steps as
.github/workflows/ci.yml)Environment: Node 24 · pnpm 9 ·
postgres:16-alpinecontainer with CI'sDATABASE_*andNODE_ENV=civariables. Exit codes captured directly from eachcommand.
git ls-files 'dist/' '*.tsbuildinfo' 'compliance/reports/'pnpm run lint:cipnpm run typecheckpnpm run buildpnpm run migrations:checkpnpm run migration:runpnpm run migration:generate:checkpnpm run migration:revertnpm run license:scanStatus: WARNING— pre-existing conditions, exit code still 0)pnpm audit --audit-level=highcontinue-on-error: truewith a comment stating this gate activates only after the inherited CVEs are remediated. Unrelated to a Markdown-only change (lockfile untouched on this branch).Post-change validations run against the final committed files:
CODE_FREEZE.mdresolve on disk(programmatically extracted and checked; the document has no external or
anchor-only links).
document —
COMMUNICATION_NORMS.md§4.3,APPROVAL_REQUIREMENTS.md§§2/5/5.3,MERGE_STRATEGY.md§1,BACKPORT.md§3,DECISION_LOG.mdentry format,processes/RELEASE_SIGNOFF.md§4.npx prettier --check 'Governance/**/*.md'flags 135 of 135Markdown files including every pre-existing policy, and CI's
format:checkcoversonly
src/**andtest/**— i.e. Markdown formatting is not enforced anywhere inthis repository. The new file deliberately follows the compact table style of its
siblings rather than introducing a one-off formatting convention.
10. Tests
npx jest src/i18n/i18n.build.spec.ts src/rate-limiting/dto/update-rate-limiting.dto.spec.ts src/incident-management/dto/incident-resolution.dto.spec.ts src/rate-limiting/services/quota-tracking.service.spec.ts --forceExit --runInBand→ 4 suites passed, 22/22 tests passed.
pnpm run test:sanityfails duringsuite load with
SyntaxError: Unexpected token 'export'while Jest importsotplib→@otplib/plugin-base32-scure(an ESM package Jest's default transformsdon't handle). I reproduced the identical failure with this change stashed
(
git stash -uonto cleanmain), proving it predates this PR. The project's CIworkflow contains no Jest job, and this branch changes no code under
src/, sothere is no causal path from this change to that failure. Fixing it belongs in a
separate code PR (it would violate this issue's ≤2-file /
Governance/-onlyconstraint here) — flagged as follow-up rather than papered over.
runtime behaviour;
Governance/is excluded from the Jest root entirely. This isthe same rationale the repository already documents for governance-only changes
(
processes/RELEASE_SIGNOFF.md§5,templates/RELEASE_CHECKLIST.md"Regression Tests Where Applicable"). §6 of the new policy goes one step further
and pre-registers the three regression assertions any future code/CI
implementation of this policy must ship with, so adding policy machinery later
can't land untested.
No check was skipped, weakened, or suppressed, and no assertion, lint rule, or type
check was modified anywhere in this PR.
11. Documentation of the change
Governance/CHANGELOG.md→[Unreleased] → Addedbullet naming thefile, summarising its coverage (triggers, declaration, allowed/prohibited changes,
exception process, enforcement, roles, regression-test guidance), and citing
issue Add a code freeze policy for TeachLink Backend #1840. Format follows Keep a Changelog, matching existing bullets.
2026-10-17) so the policy is versionable on its own terms, matching
RELEASE_BRANCHING.md,BRANCH_PROTECTION.md,VULN_SLA.md, andEMBARGO.md.policies.
12. Rollout and communication
configuration switch is involved.
freeze owner posts the pinned issue and mirrors it to the channels named in
COMMUNICATION_NORMS.md.DECISION_LOG.md,giving maintainers their first auditable exception trail for the next
transparency report (
policies/TRANSPARENCY_REPORTS.md).incident, or branch-protection process changes materially.
13. Security, compliance, and operational considerations
workflow edits — nothing to review for injection, auth, or data-handling risk.
freeze-scope and §3.1 routes their exceptions through
EMBARGO.md, so a freeze cannever delay a fix for an embargoed vulnerability or pressure anyone into premature
disclosure.
privileged path; §3.1 forbids unaudited self-approval when an independent approver
exists; §3.4's 24-hour decision-log requirement keeps exceptions accountable.
14. Known limitations and deliberate omissions
Governance/README.mdpolicy index not updated — it still lists only policiesup to the earlier batches; adding a
CODE_FREEZE.mdrow would be a third file andviolate the issue's ≤2-file cap. Recommended as an immediate follow-up.
pre-existing branch-protection gate; CI path-blocking would need changes outside
Governance/. §6 pins the tests required when that happens.test:sanityfails onmaintoday (ESM interop, evidence in §10) — out ofscope here.
pnpm auditis non-clean (§9, step 10) — pre-existing upstream CVEs theproject has explicitly gated behind
continue-on-error.prettieroutput (§9) — true of all 135Governance Markdown files and never enforced by CI.
15. How to review this PR
Governance/policies/CODE_FREEZE.mdtop to bottom (~235 lines,self-contained) — check §1 against the release/embargo/SLO documents it cites,
§2 for anything the project would realistically want prohibited-but-needed, and
§3's approver matrix against your team's actual availability.
Governance/CHANGELOG.mdaddition.git diff main --statshows the same two files.16. PR checklist
Closes #1840above; issue # cited in both changed files)Governance/Governance/exception process
pre-registered in §6
Governance/CHANGELOG.md+ in-document change history)or suppressed
Closes #1840