chore(framework): canonize Vault-as-SSOT + ESO-default secrets policy #519

Open
jason.woltje wants to merge 2 commits from chore/canonize-vault-secrets-policy into main
Owner

Summary

This PR encodes the Vault-as-source-of-truth + ESO-default secrets policy as binding framework rules, effective for all future agent work across all Mosaic projects.

Operator decision: Jason approved this wording via Discord on 2026-05-22.

Files updated

File Duplicate path Change
guides/VAULT-SECRETS.md packages/mosaic/framework/guides/VAULT-SECRETS.md Expanded with 4 new sections (decision matrix, ESO bridge example, Direct-Vault opt-in, forbidden patterns)
guides/BOOTSTRAP.md packages/mosaic/framework/guides/BOOTSTRAP.md Added "Secrets Bootstrap" required subsection with checklist
packages/mosaic/framework/defaults/STANDARDS.md (single copy in repo) Added ### Secrets handling (HARD RULE) under Non-Negotiables

Duplicate-path sync note

The framework files exist at two paths in this repo and must stay in sync:

  • guides/ <-> packages/mosaic/framework/guides/
  • packages/mosaic/framework/defaults/STANDARDS.md is the single canonical copy (no root-level defaults/ dir exists in this repo)

All pairs are md5-equal after this commit. Future maintainers: always edit both paths when modifying these files.

Policy summary (verbatim from STANDARDS.md)

  • Vault is the canonical source-of-truth for every secret in every environment. No exceptions.
  • For k8s workloads: External Secrets Operator -> k8s Secret -> env var is the default read path. No Vault client in app code.
  • Direct-Vault is opt-in only, justified per-app by a documented dynamic-secrets requirement.
  • ${VAR:-default} fallback syntax is forbidden for required values in deploy configs. Use ${VAR:?VAR is required}.
  • .env files in production deployment paths are forbidden.
  • App startup must validate required secrets via schema (zod/pydantic/equivalent) and exit non-zero on missing values.
  1. CI lint implementation: Add lint rules to the CI pipeline (.woodpecker/) that catch the forbidden patterns listed in VAULT-SECRETS.md - Forbidden Patterns -- specifically: untagged ${VAR:-default} in deploy configs, vault kv calls in app source, hardcoded credential patterns, and .env files in production paths. Initially in warning mode, then error mode per Jason's staged-rollout plan.
  2. Staged rollout: Warning mode first (log violations, do not fail build) -> Error mode after teams have had time to remediate existing violations.
  3. Existing project audit: Run the forbidden-patterns check against all current repos and open remediation issues for violations found.

Review requirement

DO NOT MERGE without operator approval. This policy binds every future agent session and every Mosaic project. Jason should review the verbatim wording before this lands on main.

## Summary This PR encodes the Vault-as-source-of-truth + ESO-default secrets policy as binding framework rules, effective for all future agent work across all Mosaic projects. **Operator decision:** Jason approved this wording via Discord on 2026-05-22. ## Files updated | File | Duplicate path | Change | |---|---|---| | `guides/VAULT-SECRETS.md` | `packages/mosaic/framework/guides/VAULT-SECRETS.md` | Expanded with 4 new sections (decision matrix, ESO bridge example, Direct-Vault opt-in, forbidden patterns) | | `guides/BOOTSTRAP.md` | `packages/mosaic/framework/guides/BOOTSTRAP.md` | Added "Secrets Bootstrap" required subsection with checklist | | `packages/mosaic/framework/defaults/STANDARDS.md` | _(single copy in repo)_ | Added `### Secrets handling (HARD RULE)` under Non-Negotiables | ## Duplicate-path sync note The framework files exist at two paths in this repo and must stay in sync: - `guides/` <-> `packages/mosaic/framework/guides/` - `packages/mosaic/framework/defaults/STANDARDS.md` is the single canonical copy (no root-level `defaults/` dir exists in this repo) All pairs are md5-equal after this commit. Future maintainers: always edit both paths when modifying these files. ## Policy summary (verbatim from STANDARDS.md) - Vault is the canonical source-of-truth for every secret in every environment. No exceptions. - For k8s workloads: External Secrets Operator -> k8s Secret -> env var is the default read path. No Vault client in app code. - Direct-Vault is opt-in only, justified per-app by a documented dynamic-secrets requirement. - `${VAR:-default}` fallback syntax is forbidden for required values in deploy configs. Use `${VAR:?VAR is required}`. - `.env` files in production deployment paths are forbidden. - App startup must validate required secrets via schema (zod/pydantic/equivalent) and exit non-zero on missing values. ## Recommended follow-up (subsequent PRs) 1. **CI lint implementation:** Add lint rules to the CI pipeline (`.woodpecker/`) that catch the forbidden patterns listed in `VAULT-SECRETS.md - Forbidden Patterns` -- specifically: untagged `${VAR:-default}` in deploy configs, `vault kv` calls in app source, hardcoded credential patterns, and `.env` files in production paths. Initially in warning mode, then error mode per Jason's staged-rollout plan. 2. **Staged rollout:** Warning mode first (log violations, do not fail build) -> Error mode after teams have had time to remediate existing violations. 3. **Existing project audit:** Run the forbidden-patterns check against all current repos and open remediation issues for violations found. ## Review requirement **DO NOT MERGE without operator approval.** This policy binds every future agent session and every Mosaic project. Jason should review the verbatim wording before this lands on main.
jason.woltje added 1 commit 2026-05-22 16:58:57 +00:00
chore(framework): canonize Vault-as-SSOT + ESO-default secrets policy
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
373e4558a3
Encodes operator-approved (Jason, 2026-05-22) secrets policy as binding
framework rules across all Mosaic agent sessions and projects.

Changes:
- STANDARDS.md: add "Secrets handling (HARD RULE)" subsection under
  Non-Negotiables — Vault as SSOT, ESO bridge as default, Direct-Vault
  opt-in only, forbidden ${VAR:-default} for required values, forbidden
  .env in prod, required startup schema validation
- VAULT-SECRETS.md: add four new sections — architecture decision matrix
  (ESO vs Direct-Vault), full ESO bridge worked example (Vault path +
  ExternalSecret + Deployment YAML + zod/pydantic/Go validators),
  Direct-Vault opt-in pattern (AppRole provisioning + ESO bootstrap
  for chicken-and-egg), and forbidden patterns CI lint targets
- BOOTSTRAP.md: add "Secrets Bootstrap" required subsection with
  checklist for new apps (Vault path, README docs, ExternalSecret,
  secretKeyRef, schema validator, Direct-Vault justification)

All duplicate file paths kept in sync (md5-equal pairs):
  guides/ <-> packages/mosaic/framework/guides/
  packages/mosaic/framework/defaults/STANDARDS.md (single copy in repo)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jason.woltje added 1 commit 2026-05-22 17:01:37 +00:00
fix(framework): remediate Codex review findings in VAULT-SECRETS.md
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
e88a89f34d
Two should-fix findings from automated Codex review:

1. Vault KV v2 policy path — add explicit path for exact top-level
   `secret/data/k3s/<app>` entry alongside the wildcard `/*` sub-path
   rule. Without the exact path, apps reading the top-level secret get
   permission denied from Vault KV v2 even with the wildcard.

2. Go envconfig example — remove unused `os` import from config.go
   snippet (os was only referenced in a comment). Move the main() usage
   to a separate clearly-labelled main.go block to make both snippets
   copy-paste compilable.

Both fixes mirrored to duplicate path:
  guides/ <-> packages/mosaic/framework/guides/

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin chore/canonize-vault-secrets-policy:chore/canonize-vault-secrets-policy
git checkout chore/canonize-vault-secrets-policy
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#519