Ctrl K
ComunidadGuías…

docs/repository-governance.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Repository governance and release policy

This document defines the target operating model for repository changes and
hosted releases. The goals are to keep production stable, preserve valuable
work in progress, and make every release reviewable and recoverable.

## Canonical branches and environments

Changes move in one direction:

```text
feature or fix branch -> development -> staging -> main
                            |             |          |
                        Development    Staging   Production
```

| Branch | Purpose | Environment | Deployment rule |
| --- | --- | --- | --- |
| `development` | Integration branch for completed feature work | Development | Deploy automatically after required checks pass |
| `staging` | Release-candidate branch; no unrelated feature work | Staging | Deploy an immutable release candidate for acceptance testing |
| `main` | Audited production history and the deployed release line | Production | Deploy only an approved artifact already tested in staging |

All three canonical branches must be protected. Direct pushes, force pushes,
and branch deletion are disabled. Required checks and reviews apply to
maintainers and administrators as well as other contributors. A bypass is an
incident action, not a normal release mechanism, and must be recorded in the
incident timeline.

`main` is the source of truth for what is in production. A deployment is not
considered a production release unless its source commit and immutable artifact
identifier are recorded against `main`.

## Normal change flow

### Feature and fix pull requests

1. Create a short-lived branch from current `development`. Before review,
   rebase it on current `development` and resolve conflicts on the topic branch.
2. Open a pull request into `development`. Do not open feature pull requests
   directly into `staging` or `main`.
3. Describe the user or operational outcome, risk, test evidence, rollout
   controls, migration impact, and rollback limits. UI changes include visual
   evidence; security- or data-sensitive changes identify their threat and
   tenant-isolation considerations.
4. Obtain the required independent and code-owner reviews, resolve all review
   threads, and pass all required checks.
5. Merge using the repository's configured merge strategy. Delete the topic
   branch only after the merge is verified and no other pull request depends on
   it.

Keep pull requests small enough to review. If a feature must be integrated
before it is ready for users, put it behind a default-off flag with an owner,
activation criteria, and removal date.

### Release pull requests

1. Open a release pull request from `development` to `staging`. Its description
   lists the included pull requests, migrations, configuration changes, feature
   flags, operator actions, acceptance plan, and rollback constraints.
2. Freeze the release candidate while it is tested. A release-blocking fix
   branches from `staging`, returns to `staging` through a reviewed pull request,
   and is immediately forward-ported to `development`.
3. Build the release artifact once, deploy that immutable artifact to the
   Staging environment, and record its digest and source commit.
4. After staging acceptance, open a production release pull request from
   `staging` to `main`. The pull request must identify the exact artifact tested
   in staging and link the release evidence.
5. After production approval, advance `main` and promote the same artifact to
   Production. Do not rebuild the production artifact from a branch name.
6. Verify production health, migrations, tenant isolation, and a minimal smoke
   path. Record the result in the release.

If `development` advances while a release candidate is in staging, those later
changes wait for the next release. Do not merge `development` into a release in
progress merely to make the branches appear synchronized.

## Required reviews and checks

Every pull request into a canonical branch requires:

- at least one approval from a reviewer other than the author;
- approval from an applicable code owner for owned paths;
- all review conversations resolved and no outstanding change requests;
- a current base branch with conflicts resolved before final approval;
- successful `build`, `Migration history integrity`, and `RLS tenant
  isolation` CI jobs; and
- the testing, security, migration, and release evidence appropriate to the
  change.

Production release pull requests require a second approval from the designated
release owner. Changes involving authentication, authorization, tenant
boundaries, migrations, clinical records, billing, secrets, webhooks, provider
integrations, recovery, CI, or deployment configuration require approval from
the relevant security, data, or operations owner in addition to the normal
reviewer. Authors cannot approve their own pull requests or deployments.

Required checks must include the repository's existing public-release scan,
production-dependency audit, type check, automated tests, build, append-only
migration-history check, schema/migration consistency checks, and real-Postgres
RLS isolation tests. A flaky or unavailable check blocks a release until it is
fixed or an incident-scoped exception is documented and approved by both the
release and relevant code owner.

## CODEOWNERS policy

The repository must maintain `.github/CODEOWNERS` using teams or durable roles,
not a single individual's account. At minimum, it should assign ownership for:

- default repository-wide review;
- authentication, authorization, tenant scoping, and RLS;
- database schema, migrations, and recovery tooling;
- billing, messaging, email, webhooks, and external providers;
- CI workflows, deployment configuration, and release runbooks; and
- security policy and dependency controls.

Code ownership is a review boundary, not merely a notification list. Owners are
responsible for assessing failure modes, migration and rollback limits, data
exposure, and operational readiness in their area. Ownership changes require a
review from the existing owner or the repository maintainers and must not leave
a sensitive path unowned.

During the transition, the current maintainer account may bootstrap ownership
so sensitive paths are not left unowned. Replace that temporary entry with
durable teams before enabling independent code-owner approval as a required
merge condition.

## Database migration policy

Production migrations follow an expand-and-contract sequence:

1. **Expand:** add backward-compatible tables, columns, indexes, policies, or
   dual-read/write support. Committed migration history is append-only; never
   edit a migration that may have run in any shared environment.
2. **Migrate:** backfill in bounded, observable batches. Make retries safe,
   retain evidence of completion, and avoid long locks on live tables.
3. **Switch:** deploy code that uses the new shape only after the expansion is
   proven in Development and Staging. Keep rollback compatibility with the
   prior artifact for the declared rollback window.
4. **Contract:** remove old reads, writes, columns, tables, or policies in a
   separate release after the old application version and all backfills are
   confirmed inactive.

A pull request must not combine an incompatible schema contraction with the
code that first depends on the replacement. Production uses committed
migrations and reapplies and verifies RLS; it must not use schema-push tooling.
Before a high-risk migration, verify current backup and restore evidence,
estimate lock and runtime behavior, define abort thresholds, and identify
whether rollback means artifact rollback, a forward data repair, or restore.

## Production release control

The release pipeline must build an immutable artifact from the approved staging
commit, store its digest, and deploy that same digest to Staging and Production.
The production environment must require an explicit approval from a release
owner who did not author the release. Environment credentials are scoped to the
environment and unavailable to pull-request code.

Each production release record contains:

- the `main` commit, staging source commit, and immutable artifact digest;
- included pull requests and user-visible release notes;
- required-check results and staging acceptance evidence;
- migrations, configuration changes, feature-flag state, and operator steps;
- named approvers, approval time, and deployment time; and
- the rollback artifact and any database rollback limitation.

Production promotion is serialized: only one release or migration operation may
modify Production at a time. Health checks and smoke tests must complete before
the release is declared successful.

## Preview and non-production credential isolation

Pull-request code is untrusted until it has passed review. A preview deployment
must never receive a credential that can mutate Production, even when the
preview uses a separate database. Development and Staging require distinct
databases, auth/session secrets, mail/provider credentials, webhook endpoints
and signing secrets, object-storage credentials, billing test-mode keys, and
least-privilege cloud identities. Default-off provider and fee-bearing flags
remain off in both environments.

The 2026-08-25 audit found that `openvpm-app` Preview used a different database
but several Preview credentials had values identical to Production, including
Stripe, Resend, webhook, MFA, cron, and replica credentials. New non-production
builds are therefore quarantined in Vercel while credentials are separated and
rotated. The `openvpm` demo project already skipped non-production builds and
now remains under the same quarantine boundary. This is an incident-prevention
control, not the completed Development or Staging environment.

The initial containment narrowed shared Resend and auth secrets to Production,
removed only Preview credential entries proven byte-identical to retained
Production copies, removed the stale branch-specific build override, and
enabled Vercel Authentication for every app deployment except the customer
custom domains. The remaining app Preview secrets are limited to a distinct
database, auth secret, Blob token, and GCP service account; the demo Preview has
a distinct database only. This scoping—not the repository-owned ignore
script—is the security boundary, because pull-request code can modify its own
`vercel.json`. The ignore script remains defense in depth. Historical exposure
still makes the retained Production values rotation candidates.

Before enabling either canonical non-production branch:

1. provision environment-specific data stores and provider test accounts;
2. create new non-production credentials rather than copying Production;
3. remove every Production-capable credential from Preview and rotate any
   Production credential that was previously available to preview code;
4. configure explicit Development and Staging branch/environment mappings;
5. prove a canary pull request receives only its intended environment and
   cannot access Production data or providers; and
6. record the Vercel project, deployment, source SHA, variable-scope audit, and
   smoke-test evidence before lifting the quarantine.

The placeholder `openvpm-docs` project is separately quarantined with an
Ignored Build Step of `test ! -f .vercel-deploy-enabled`. Adding that sentinel
is an explicit release decision requiring a focused docs pull request, build
evidence, domains and environment review, and an owner. Package metadata alone
must not infer that unfinished docs WIP is ready to deploy.

## Rollback and incident path

When a release causes harm or threatens data, tenant isolation, security, or
availability:

1. Stop further promotions and name an incident lead.
2. Preserve logs and deployment evidence, identify the affected artifact and
   migration state, and disable the smallest relevant feature or integration if
   a safe kill switch exists.
3. If the database remains compatible, promote the last known-good immutable
   artifact. Do not rebuild an old branch.
4. If a migration or data write makes artifact rollback unsafe, hold the
   rollout and use a reviewed forward repair. Restore data only under the
   backup/restore runbook with an explicit data-loss and tenant-impact review.
5. For an urgent code repair, branch from `main`, use an expedited but reviewed
   pull request with the required checks, and deploy through the production
   approval gate. Immediately forward-port the repair to `staging` and
   `development`.
6. Record detection, decisions, approvals, customer impact, recovery, and
   follow-up work. Rotate credentials promptly if exposure is possible and
   complete a blameless post-incident review.

The incident lead may shorten timing, but may not silently waive auditability,
independent review, tenant-safety checks, or release recording.

## Branch and pull-request cleanup

Cleanup is an evidence-preservation exercise, not a bulk deletion event.
The active item-by-item decisions are recorded in the
[repository recovery and cleanup ledger](repository-recovery-ledger.md).

### Phase 0: Stabilize

- Pause nonessential production merges and all branch deletion.
- Declare the deployed `main` commit as the baseline.
- Back up repository metadata and record all open pull requests, remote
  branches, tags, and deployment-linked commits.
- Assign a cleanup owner and use a shared register for every branch and pull
  request.

### Phase 1: Inventory and classify

For each item, record its owner, purpose, base and head commits, open pull
request, last activity, unique commits, deployment history, dependencies,
migrations, security or tenant impact, and test state. Classify it as:

- merged or already equivalent to `main`;
- active and owned;
- valuable but needing recovery;
- superseded, abandoned, or generated; or
- unknown/high-risk and requiring specialist review.

No unknown or high-risk item is deleted merely because it is old.

### Phase 2: Recover valuable work

Recreate valuable changes as small, current branches based on `development`.
Prefer reviewed cherry-picks or a clean reimplementation over merging a stale
branch wholesale. Re-run current checks and give migrations, authentication,
tenant boundaries, billing, messaging, and provider changes specialist review.
Link the replacement pull request to the original so authorship and decisions
remain discoverable.

### Phase 3: Close superseded work

Close a pull request only after recording why it is obsolete, merged elsewhere,
or replaced, with a link to the successor when one exists. Delete its remote
branch only after confirming that all valuable unique commits are merged or
preserved and no open work depends on it. Require two-maintainer approval for
cleanup of a branch with migrations, deployment history, or uncertain ownership.

### Phase 4: Prune and maintain

After a published grace period, prune approved merged or superseded branches,
verify that canonical and release references remain reachable, and publish a
cleanup summary. Enable automatic deletion only for merged topic branches, not
canonical or release references. Repeat the inventory on a regular cadence so
the backlog does not regrow.

## Retiring Orca as repository authority

Orca worktrees and automation are not canonical repository state. Retire them
in a controlled handoff:

1. Freeze new work in Orca and inventory every Orca worktree, uncommitted
   change, unique commit, open pull request, automation, and credential scope.
2. Recover valuable work through reviewed branches and pull requests in the
   canonical flow. Preserve provenance by linking the source worktree or pull
   request in the cleanup register without publishing local paths or secrets.
3. Prove that Development, Staging, and Production deploy successfully under
   the new branch protections, environment approvals, and release recording.
4. Disable Orca jobs and repository write access, then revoke its credentials
   and webhooks. Verify that no required deployment, scheduled job, or recovery
   process depended on them.
5. Remove Orca worktrees only after all unique work is preserved and the grace
   period has passed.

Standard local clones and Git worktrees may still be used as working copies;
the protected remote branches, reviewed pull requests, immutable artifacts, and
release records remain authoritative.

## Transition note — 2026-08-25

This policy describes the target state, not controls that are already fully in
place. At the start of this transition:

- `main` is the deployed branch and automatically deploys today;
- `staging` exists but is stale and materially behind `main`;
- `development` does not exist;
- pull-request CI is configured for `main`, not all three canonical branches;
- the migration workflow runs from pushes to `main`;
- `.github/CODEOWNERS` does not exist; and
- protected-environment approval and exact-artifact promotion have not yet been
  established by this document alone.

Until the transition is complete, treat every merge to `main` as an immediate
production change. Do not use `staging` for release decisions while it is stale,
and do not delete branches or close pull requests before completing the
inventory.

The initial governance change adds a transitional fail-closed release lock.
Automatic Vercel builds from `main` are only candidates: a Production build
fails unless `PRODUCTION_RELEASE_SHA` equals that deployment's exact
`VERCEL_GIT_COMMIT_SHA`. Production migrations must be dispatched from `main`
with the same 40-character commit and the typed confirmation
`MIGRATE_PRODUCTION`. After migrations and drift checks pass, set the exact SHA
in each production-target Vercel project, redeploy that exact candidate, run
health and smoke checks, and then clear or rotate the value. Until protected
environment reviewers are configured, the SHA value is a kill switch and audit
aid—not proof of independent approval. It is superseded by build-once artifact
promotion when the target pipeline is ready.

The initial control rollout is:

1. Record the current deployed `main` commit and restrict `main` to approved,
   checked production changes.
2. Create `development` from that exact `main` commit.
3. Preserve the current `staging` tip, then fast-forward `staging` to the same
   baseline through a reviewed maintainer operation.
4. Add branch protection, CODEOWNERS, and required CI coverage for
   `development`, `staging`, and `main`.
5. Configure distinct Development, Staging, and Production environments with
   scoped credentials and production deployment approval.
6. Implement build-once artifact recording and promotion, then rehearse a
   normal release and rollback before resuming routine production delivery.
7. Run the phased branch and pull-request inventory, recovery, and cleanup.

Do not protect `development` or `staging` while they still point at the old
deployed baseline: that baseline's CI workflow emits canonical-branch checks
only for `main`, which would deadlock required checks. First merge, deploy, and
verify the governance commit on `main`; then create or fast-forward both
branches to that exact deployed SHA and apply their no-bypass protections.

Any step that would rewrite or delete a remote ref requires a preserved
reference, a reviewed change record, and explicit maintainer approval.