mandrel-platform 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mandrel-platform",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Shared CI/deploy workflows, composite toolchain action, npm config package, Renovate preset, and operator runbook templates.",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -0,0 +1,42 @@
1
+ # Runbook Templates (copyable thin stubs)
2
+
3
+ These are **copyable thin-stub templates** — one per canonical mandrel-platform
4
+ runbook in [`docs/runbooks/`](https://github.com/dsj1984/mandrel-platform/tree/main/docs/runbooks).
5
+ They implement the MP-9 adoption model (§7.7 / F1): *replace each duplicated
6
+ process runbook with a thin local doc that holds project-specific values plus a
7
+ link to the canonical runbook.*
8
+
9
+ Each stub:
10
+
11
+ - **Links** to its canonical mandrel-platform runbook (the process source of
12
+ truth — do not re-author the process here).
13
+ - Carries **placeholders** for project-specific values in `<ANGLE_BRACKET>`
14
+ form (hosts, env names, dashboards, DB engine, worker names, …).
15
+
16
+ ## How to adopt (downstream repo)
17
+
18
+ 1. Copy the stub(s) you need into your project's `docs/runbooks/`:
19
+ ```bash
20
+ cp node_modules/mandrel-platform/templates/runbooks/deploy-promotion.md \
21
+ docs/runbooks/deploy-promotion.md
22
+ ```
23
+ 2. Replace every `<PLACEHOLDER>` with your project's real values.
24
+ 3. Fill in the **Project-Specific Notes** section.
25
+ 4. Leave the canonical link intact — when the upstream process changes, you only
26
+ re-read the link, not rewrite the stub.
27
+
28
+ ## Stubs
29
+
30
+ | Stub | Canonical runbook |
31
+ |------|-------------------|
32
+ | `deploy-promotion.md` | staging → production promotion |
33
+ | `incident-response.md` | severity, escalation, postmortem |
34
+ | `database-backup-restore.md` | backup, PITR, restore/rollback |
35
+ | `observability.md` | logs, Sentry, uptime, metrics |
36
+ | `post-deploy-smoke.md` | boot-smoke gate + diagnosis |
37
+ | `environments-provisioning.md` | env model + provisioning steps |
38
+ | `dependency-update.md` | Renovate, CVE gate, catalog |
39
+ | `branch-protection-setup.md` | aggregator required-check model |
40
+
41
+ > Placeholder convention: `<UPPER_SNAKE>` between angle brackets. Search for
42
+ > `<` after copying to find everything that still needs a value.
@@ -0,0 +1,45 @@
1
+ # Branch Protection Setup — <PROJECT_NAME>
2
+
3
+ > **Thin local stub.** The canonical single-aggregator protection model and the
4
+ > `main-protection.json` contract live in the mandrel-platform repo:
5
+ > [`docs/runbooks/branch-protection-setup.md`](https://github.com/dsj1984/mandrel-platform/blob/main/docs/runbooks/branch-protection-setup.md).
6
+ > This file only holds **<PROJECT_NAME>-specific check names and reviewers**.
7
+
8
+ ---
9
+
10
+ ## Project Values
11
+
12
+ | Value | Setting |
13
+ |-------|---------|
14
+ | Repo (`owner/repo`) | `<OWNER>/<REPO>` |
15
+ | Protected branch | `<PROTECTED_BRANCH>` (e.g. `main`) |
16
+ | Required aggregator check | `<AGGREGATOR_CHECK>` (e.g. `ci-required`) |
17
+ | Protection contract file | `<MAIN_PROTECTION_JSON>` (e.g. `docs/runbooks/main-protection.json`) |
18
+ | Reviewer group(s) | `<REVIEWER_GROUPS>` |
19
+ | GitHub plan | `<GITHUB_PLAN>` (free / pro / team) |
20
+
21
+ ## Apply & Verify
22
+
23
+ ```bash
24
+ # Preview / apply
25
+ node scripts/apply-branch-protection.mjs --dry-run
26
+ node scripts/apply-branch-protection.mjs --apply
27
+
28
+ # Verify
29
+ gh api repos/<OWNER>/<REPO>/branches/<PROTECTED_BRANCH>/protection \
30
+ --jq '.required_status_checks.contexts'
31
+ # Expected: ["<AGGREGATOR_CHECK>"]
32
+ ```
33
+
34
+ > **Do not add individual job names as required checks** — only the aggregator.
35
+
36
+ ## Project-Specific Notes
37
+
38
+ <!-- Ruleset IDs, enforceAdmins rationale, plan-specific constraints. -->
39
+
40
+ - _TODO: fill in._
41
+
42
+ ---
43
+
44
+ See also the project's `<MAIN_PROTECTION_JSON>` and the local stubs:
45
+ `dependency-update.md`, `environments-provisioning.md`.
@@ -0,0 +1,49 @@
1
+ # Database Backup & Restore — <PROJECT_NAME>
2
+
3
+ > **Thin local stub.** The canonical backup strategy, PITR procedure, and
4
+ > restore steps live in the mandrel-platform repo:
5
+ > [`docs/runbooks/database-backup-restore.md`](https://github.com/dsj1984/mandrel-platform/blob/main/docs/runbooks/database-backup-restore.md).
6
+ > This file only holds **<PROJECT_NAME>-specific database values**.
7
+
8
+ ---
9
+
10
+ ## Project Values
11
+
12
+ | Value | Setting |
13
+ |-------|---------|
14
+ | DB engine | `<DB_ENGINE>` (e.g. Turso/libSQL) |
15
+ | Staging DB name | `<STAGING_DB_NAME>` |
16
+ | Production DB name | `<PRODUCTION_DB_NAME>` |
17
+ | Org / account | `<DB_ORG>` |
18
+ | PITR retention window | `<PITR_WINDOW>` (e.g. 7 days) |
19
+ | Critical tables (integrity check) | `<CRITICAL_TABLE>` |
20
+ | Worker secret for DB URL | `<DATABASE_URL_SECRET>` |
21
+ | Backup verification log | `<BACKUP_VERIFY_LOG_LOCATION>` |
22
+
23
+ ## Restore from Pre-Deploy Snapshot (primary path)
24
+
25
+ ```bash
26
+ SNAPSHOT_BRANCH="<SNAPSHOT_BRANCH>" # from the deploy workflow run output
27
+ turso db create <PRODUCTION_DB_NAME>-restored \
28
+ --from-db <PRODUCTION_DB_NAME> --from-branch "$SNAPSHOT_BRANCH"
29
+ turso db shell <PRODUCTION_DB_NAME>-restored "SELECT COUNT(*) FROM <CRITICAL_TABLE>;"
30
+ # Repoint the worker secret and redeploy — see canonical Section 5.
31
+ ```
32
+
33
+ ## Manual Backup
34
+
35
+ ```bash
36
+ turso db branch create <PRODUCTION_DB_NAME> backup-$(date +%Y%m%d)
37
+ turso db shell <PRODUCTION_DB_NAME> ".dump" > backup-$(date +%Y%m%d).sql # store securely
38
+ ```
39
+
40
+ ## Project-Specific Notes
41
+
42
+ <!-- Snapshot cadence, who owns restores, where dumps are archived. -->
43
+
44
+ - _TODO: fill in._
45
+
46
+ ---
47
+
48
+ See also the local stubs: `rollback.md`, `deploy-promotion.md`,
49
+ `incident-response.md`, and the project's `docs/environments.md`.
@@ -0,0 +1,40 @@
1
+ # Dependency Update — <PROJECT_NAME>
2
+
3
+ > **Thin local stub.** The canonical Renovate model, CVE gate, catalog, and
4
+ > override conventions live in the mandrel-platform repo:
5
+ > [`docs/runbooks/dependency-update.md`](https://github.com/dsj1984/mandrel-platform/blob/main/docs/runbooks/dependency-update.md).
6
+ > This file only holds **<PROJECT_NAME>-specific configuration pointers**.
7
+
8
+ ---
9
+
10
+ ## Project Values
11
+
12
+ | Value | Setting |
13
+ |-------|---------|
14
+ | Package manager | `<PACKAGE_MANAGER>` (e.g. pnpm) |
15
+ | Renovate config | `<RENOVATE_CONFIG_PATH>` |
16
+ | CVE allowlist location | `<CVE_ALLOWLIST_PATH>` |
17
+ | Audit command | `<AUDIT_COMMAND>` (e.g. `pnpm run audit:check`) |
18
+ | Renovate Dependency Dashboard | `<DASHBOARD_ISSUE_URL>` |
19
+ | Node version pin | `<NODE_VERSION>` (`.nvmrc`) |
20
+
21
+ ## Common Commands
22
+
23
+ ```bash
24
+ # Run the CVE gate locally (what CI sees)
25
+ <AUDIT_COMMAND>
26
+
27
+ # Out-of-band update
28
+ <PACKAGE_MANAGER> update <package-name>
29
+ ```
30
+
31
+ ## Project-Specific Notes
32
+
33
+ <!-- Renovate preset overrides, grouped packages, manual-merge policies. -->
34
+
35
+ - _TODO: fill in._
36
+
37
+ ---
38
+
39
+ See also the local stubs: `secret-rotation.md`, `incident-response.md`, and
40
+ the project's `docs/environments.md`.
@@ -0,0 +1,47 @@
1
+ # Deploy Promotion — <PROJECT_NAME>
2
+
3
+ > **Thin local stub.** The canonical, process-level procedure lives in the
4
+ > mandrel-platform repo:
5
+ > [`docs/runbooks/deploy-promotion.md`](https://github.com/dsj1984/mandrel-platform/blob/main/docs/runbooks/deploy-promotion.md).
6
+ > This file only holds **<PROJECT_NAME>-specific values**. When the process
7
+ > changes, update the canonical runbook upstream — not this stub.
8
+
9
+ ---
10
+
11
+ ## Project Values
12
+
13
+ | Value | Setting |
14
+ |-------|---------|
15
+ | Staging worker name | `<STAGING_WORKER_NAME>` |
16
+ | Production worker name | `<PRODUCTION_WORKER_NAME>` |
17
+ | Staging deploy workflow | `<STAGING_DEPLOY_WORKFLOW>` (e.g. `deploy-staging.yml`) |
18
+ | Production deploy workflow | `<PRODUCTION_DEPLOY_WORKFLOW>` (e.g. `deploy-production.yml`) |
19
+ | Production health URL | `<PRODUCTION_HEALTH_URL>` |
20
+ | Staging health URL | `<STAGING_HEALTH_URL>` |
21
+ | Promotion approvers | `<APPROVER_HANDLES>` |
22
+ | Deploy-window channel | `<DEPLOY_CHANNEL>` |
23
+
24
+ ## Trigger a Production Promotion
25
+
26
+ ```bash
27
+ gh workflow run <PRODUCTION_DEPLOY_WORKFLOW> --ref main --field confirm=true
28
+ ```
29
+
30
+ ## Verify
31
+
32
+ ```bash
33
+ curl -sf <PRODUCTION_HEALTH_URL> && echo OK || echo FAIL
34
+ wrangler deployments list --name <PRODUCTION_WORKER_NAME> | head -3
35
+ ```
36
+
37
+ ## Project-Specific Notes
38
+
39
+ <!-- Record any promotion quirks for this project: extra pre-checks, manual
40
+ migration steps, stakeholder sign-off requirements, etc. -->
41
+
42
+ - _TODO: fill in._
43
+
44
+ ---
45
+
46
+ See also the local stubs: `rollback.md`, `post-deploy-smoke.md`,
47
+ `incident-response.md`, and the project's `docs/environments.md`.
@@ -0,0 +1,42 @@
1
+ # Environments Provisioning — <PROJECT_NAME>
2
+
3
+ > **Thin local stub.** The canonical environment model and step-by-step
4
+ > provisioning procedure live in the mandrel-platform repo:
5
+ > [`docs/runbooks/environments-provisioning.md`](https://github.com/dsj1984/mandrel-platform/blob/main/docs/runbooks/environments-provisioning.md).
6
+ > This file only holds **<PROJECT_NAME>-specific IDs and names**.
7
+
8
+ ---
9
+
10
+ ## Project Values
11
+
12
+ | Value | Setting |
13
+ |-------|---------|
14
+ | Repo (`owner/repo`) | `<OWNER>/<REPO>` |
15
+ | Cloudflare account ID | `<CF_ACCOUNT_ID>` |
16
+ | Zone / domain | `<ZONE>` |
17
+ | Worker base name | `<WORKER_NAME>` |
18
+ | Staging domain | `<STAGING_DOMAIN>` |
19
+ | Production domain | `<PRODUCTION_DOMAIN>` |
20
+ | Secrets manager project | `<SECRETS_PROJECT_ID>` (e.g. Infisical) |
21
+ | Staging DB name | `<STAGING_DB_NAME>` |
22
+ | Production DB name | `<PRODUCTION_DB_NAME>` |
23
+
24
+ ## Environment Map
25
+
26
+ | Environment | Branch | Deployed by |
27
+ |-------------|--------|-------------|
28
+ | `local` | any | developer (`wrangler dev`) |
29
+ | `staging` | `main` (auto) | CI/CD after CI-green |
30
+ | `production` | `main` (manual) | `workflow_dispatch` |
31
+
32
+ ## Project-Specific Notes
33
+
34
+ <!-- Custom domains, reviewer requirements, secret-sync specifics. -->
35
+
36
+ - _TODO: fill in._
37
+
38
+ ---
39
+
40
+ The authoritative environment inventory (URLs, secret names, DB names) is the
41
+ project's own `docs/environments.md`. See also the local stubs:
42
+ `branch-protection-setup.md`, `secret-rotation.md`, `deploy-promotion.md`.
@@ -0,0 +1,52 @@
1
+ # Incident Response — <PROJECT_NAME>
2
+
3
+ > **Thin local stub.** The canonical severity model, escalation flow, response
4
+ > steps, and postmortem template live in the mandrel-platform repo:
5
+ > [`docs/runbooks/incident-response.md`](https://github.com/dsj1984/mandrel-platform/blob/main/docs/runbooks/incident-response.md).
6
+ > This file only holds **<PROJECT_NAME>-specific contacts and links**.
7
+
8
+ ---
9
+
10
+ ## Escalation Contacts
11
+
12
+ | Role | Who | Channel |
13
+ |------|-----|---------|
14
+ | First responder / on-call | `<ONCALL_HANDLE>` | `<ONCALL_CHANNEL>` |
15
+ | On-call lead (P1/P2) | `<LEAD_HANDLE>` | `<LEAD_CHANNEL>` |
16
+ | Stakeholder notify (P1) | `<STAKEHOLDER_LIST>` | `<STAKEHOLDER_CHANNEL>` |
17
+
18
+ ## Tooling Links
19
+
20
+ | Tool | URL |
21
+ |------|-----|
22
+ | Error tracking (Sentry) | `<SENTRY_PROJECT_URL>` |
23
+ | Uptime (Better Stack) | `<BETTERSTACK_URL>` |
24
+ | Status page | `<STATUS_PAGE_URL>` |
25
+ | Incident issue label | `incident`, `severity::P1` … |
26
+
27
+ ## Severity SLAs (from canonical — confirm or override)
28
+
29
+ | Severity | Target response |
30
+ |----------|-----------------|
31
+ | P1 — Critical | < 15 min |
32
+ | P2 — High | < 1 hour |
33
+ | P3 — Medium | < 4 hours |
34
+ | P4 — Low | next business day |
35
+
36
+ ## First Moves
37
+
38
+ 1. Acknowledge the alert in `<BETTERSTACK_URL>` / `<SENTRY_PROJECT_URL>`.
39
+ 2. Open an incident issue (`incident` + `severity::*`).
40
+ 3. **Recent deploy? Rollback first** — see `rollback.md`.
41
+ 4. Follow the full response steps in the canonical runbook.
42
+
43
+ ## Project-Specific Notes
44
+
45
+ <!-- Paging procedures, escalation timeouts, known fragile subsystems. -->
46
+
47
+ - _TODO: fill in._
48
+
49
+ ---
50
+
51
+ See also the local stubs: `rollback.md`, `observability.md`,
52
+ `secret-rotation.md`, and the project's `docs/environments.md`.
@@ -0,0 +1,49 @@
1
+ # Observability — <PROJECT_NAME>
2
+
3
+ > **Thin local stub.** The canonical observability stack, query patterns, and
4
+ > on-call response flow live in the mandrel-platform repo:
5
+ > [`docs/runbooks/observability.md`](https://github.com/dsj1984/mandrel-platform/blob/main/docs/runbooks/observability.md).
6
+ > This file only holds **<PROJECT_NAME>-specific endpoints and dataset names**.
7
+
8
+ ---
9
+
10
+ ## Project Values
11
+
12
+ | Value | Setting |
13
+ |-------|---------|
14
+ | Worker name(s) | `<WORKER_NAME>` |
15
+ | Cloudflare account ID | `<CF_ACCOUNT_ID>` |
16
+ | Analytics Engine dataset | `<AE_DATASET>` |
17
+ | Sentry dashboard | `<SENTRY_PROJECT_URL>` |
18
+ | Sentry DSN secret | `<SENTRY_DSN_SECRET>` |
19
+ | Better Stack dashboard | `<BETTERSTACK_URL>` |
20
+ | Logpush destination | `<LOGPUSH_DESTINATION>` |
21
+
22
+ ## Quick Commands
23
+
24
+ ```bash
25
+ # Live tail
26
+ wrangler tail --name <WORKER_NAME> --format pretty
27
+
28
+ # Errors only
29
+ wrangler tail --name <WORKER_NAME> --format json | jq 'select(.outcome != "ok")'
30
+ ```
31
+
32
+ ## Alert Thresholds (from canonical — confirm or override)
33
+
34
+ | Metric | Action threshold |
35
+ |--------|------------------|
36
+ | 5xx rate | > 1% sustained → consider rollback |
37
+ | P99 response time | > 2× baseline → investigate |
38
+ | Uptime probe failing | any failure → page on-call |
39
+
40
+ ## Project-Specific Notes
41
+
42
+ <!-- Custom dashboards, known noisy alerts, dataset schema notes. -->
43
+
44
+ - _TODO: fill in._
45
+
46
+ ---
47
+
48
+ See also the local stubs: `incident-response.md`, `rollback.md`, `slo.md`,
49
+ and the project's `docs/environments.md`.
@@ -0,0 +1,39 @@
1
+ # Post-Deploy Smoke — <PROJECT_NAME>
2
+
3
+ > **Thin local stub.** The canonical smoke contract, failure diagnosis, and
4
+ > auto-rollback behavior live in the mandrel-platform repo:
5
+ > [`docs/runbooks/post-deploy-smoke.md`](https://github.com/dsj1984/mandrel-platform/blob/main/docs/runbooks/post-deploy-smoke.md).
6
+ > This file only holds **<PROJECT_NAME>-specific health URLs and parameters**.
7
+
8
+ ---
9
+
10
+ ## Project Values
11
+
12
+ | Value | Setting |
13
+ |-------|---------|
14
+ | Staging health URL | `<STAGING_HEALTH_URL>` |
15
+ | Production health URL | `<PRODUCTION_HEALTH_URL>` |
16
+ | Health route | `<HEALTH_ROUTE>` (e.g. `GET /health`) |
17
+ | Smoke script | `<SMOKE_SCRIPT>` (e.g. `./scripts/smoke-deploy.sh`) |
18
+ | Max attempts | `<SMOKE_MAX_ATTEMPTS>` (default 5) |
19
+ | Delay between retries | `<SMOKE_DELAY_SECONDS>` (default 10s) |
20
+
21
+ ## Run the Smoke Manually
22
+
23
+ ```bash
24
+ <SMOKE_SCRIPT> <PRODUCTION_HEALTH_URL> <SMOKE_MAX_ATTEMPTS> <SMOKE_DELAY_SECONDS>
25
+
26
+ # One-shot check
27
+ curl -sf <PRODUCTION_HEALTH_URL> && echo OK || echo FAIL
28
+ ```
29
+
30
+ ## Project-Specific Notes
31
+
32
+ <!-- Cold-start tuning, non-standard health checks, auth exceptions. -->
33
+
34
+ - _TODO: fill in._
35
+
36
+ ---
37
+
38
+ See also the local stubs: `rollback.md`, `deploy-promotion.md`,
39
+ `observability.md`, and the project's `docs/environments.md`.
File without changes