@mutmutco/claude-plugin 4.6.3 → 4.6.4
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/.claude-plugin/plugin.json +1 -1
- package/cli/dist/main.cjs +544 -119
- package/cli/package.json +1 -1
- package/package.json +1 -1
- package/skills/board/SKILL.md +12 -11
- package/skills/board/reference.md +5 -1
- package/skills/bootstrap/SKILL.md +5 -5
- package/skills/bootstrap/reference.md +16 -77
- package/skills/epic/SKILL.md +3 -3
- package/skills/hotfix/SKILL.md +10 -12
- package/skills/hotfix/recovery.md +3 -7
- package/skills/intercom-guest/SKILL.md +6 -7
- package/skills/mmi-help/SKILL.md +5 -4
- package/skills/org-guide/SKILL.md +18 -27
- package/skills/org-guide/references/design.md +301 -0
- package/skills/org-guide/references/vault.md +2 -9
- package/skills/org-guide/references/work-and-releases.md +6 -297
- package/skills/rcand/SKILL.md +5 -9
- package/skills/rcand/recovery.md +1 -10
- package/skills/rcand/suite.md +1 -1
- package/skills/release/SKILL.md +7 -11
- package/skills/release/recovery.md +1 -2
- package/skills/release/suite.md +1 -1
- package/skills/release/train-common.md +28 -0
- package/skills/release/verification.md +11 -46
- package/skills/secrets/SKILL.md +6 -5
- package/skills/secrets/reference.md +5 -47
|
@@ -8,18 +8,18 @@ Do not use a `--jq` formatter, raw `gh` reads (`gh run list`, `gh run list --com
|
|
|
8
8
|
|
|
9
9
|
## Release summary file
|
|
10
10
|
|
|
11
|
-
Required for MMI-Hub and any product whose META carries `releaseChannel`; an mm-work suite repo needs one for its GitHub Release, following the update-notes template in [suite.md](suite.md).
|
|
11
|
+
Required for MMI-Hub and any product whose META carries `releaseChannel`; an mm-work suite repo needs one for its GitHub Release, following the update-notes template in [suite.md](suite.md). Run `mkdir -p .jerv/tmp` and write 3–6 lines to a file made by `mktemp .jerv/tmp/release-summary.XXXXXX` (scratch lives under `.jerv/tmp` in every repo; a repo-root `tmp/` may not exist and a host guards root writes).
|
|
12
12
|
|
|
13
13
|
- MMI-Hub: neutral Hub-subsystem terms, never a product or brand name or a Jerv-side project (the train refuses one). Build every line from `git log --stat --format='%h %s%n%b' origin/main..origin/development`; a line you cannot point to there stays out, and every cited `#N` must appear there.
|
|
14
14
|
- Product: in `releaseLanguage` (default `en`), plain words on what changed and why it matters; no prefixes, issue/PR numbers, file names or jargon.
|
|
15
15
|
|
|
16
16
|
## Receipt fields
|
|
17
17
|
|
|
18
|
-
Read the saved result, never the exit code (`1` = a follow-up failed after promotion; pending exits `0`).
|
|
18
|
+
Read the saved result, never the exit code (`1` = a follow-up failed after promotion; pending exits `0`). Keep stderr visible: the CLI prints `Release: ` stages and an elapsed update every 30 seconds, and JSON plus `--out` stay the verification record, so never redirect both streams into the result file. Name a pending step as pending; say "Release complete" only after the status fields prove every required follow-up complete.
|
|
19
19
|
|
|
20
20
|
- `releaseVerdict.releaseStatus` + `followUpStatus`: `succeeded` + `pending` is shipped, follow-up unresolved. `--resume` receipts carry the same `releaseVerdict` (`command: release-resume`) plus `mode` and `state`.
|
|
21
21
|
- `deployStatus`: `pending` is never terminal; `promoted: true` holds even when a deploy failed.
|
|
22
|
-
- `workflowRuns`: every run on the release SHA; `parallel: true` marks legs run together. Name the red run: `deploy.yml`, `publish.yml`, `tenant-deploy.yml` and `jerv-gateway` are deploy/publish verdicts; a `gate` push run is ordinary CI.
|
|
22
|
+
- `workflowRuns`: every run on the release SHA (discover them with the bounded run-list read at the top, filtered locally by the receipt SHA); watch each non-success entry to conclusion with `mmi-cli devops read run watch <run-id> --repo {owner}/{repo} --exit-status --interval 60`. `parallel: true` marks legs run together. Name the red run: `deploy.yml`, `publish.yml`, `tenant-deploy.yml` and `jerv-gateway` are deploy/publish verdicts; a `gate` push run is ordinary CI.
|
|
23
23
|
- `announceNote`: `announced`, `skipped`, `not announced` (deploy/publish not green; a `--resume` with the same `--announce-summary-file` posts it), or the failure note. A failed announcement keeps its summary file; an uncertain delivery is never replayed automatically. Never install AWS, ask for AWS credentials, or copy the Slack key.
|
|
24
24
|
- `devRollForward` / `rcAlignment`: `pushed`, or `pr-pending` with an alignment PR to land by true merge; read `autoMergeRequest.mergeMethod` from `mmi-cli devops read pr view <n> --repo {owner}/{repo} --json autoMergeRequest`: it must be `MERGE`, and `SQUASH` is a stop.
|
|
25
25
|
- `versionFold`, `rcRetirement`, `checkout`: `returned`, or the reason you are still on `main`.
|
|
@@ -27,52 +27,17 @@ Read the saved result, never the exit code (`1` = a follow-up failed after promo
|
|
|
27
27
|
|
|
28
28
|
## Lane rules
|
|
29
29
|
|
|
30
|
-
Full track ships exactly what is on `rc` (never `development`): `rc → main`. Direct track ships `development → main`, no `/rcand`; `releaseTrack: direct` in META, absent = full, and MMI-Hub is always direct. `--dev` on a full track ships `development → main` skipping rc and fails closed when `origin/rc` has content not in `development`. Never infer the lane from branch names, tags or history. Start branch: `rc`; `development` for direct-track and `--dev`.
|
|
30
|
+
Full track ships exactly what is on `rc` (never `development`): `rc → main`. Direct track ships `development → main`, no `/rcand`; `releaseTrack: direct` in META, absent = full, and MMI-Hub is always direct. `--dev` on a full track ships `development → main` skipping rc and fails closed when `origin/rc` has content not in `development`. Never infer the lane from branch names, tags or history. Start branch: `rc`; `development` for direct-track and `--dev`. A Jerv-Hub release on Windows runs under Git Bash (`"C:/Program Files/Git/bin/bash.exe" -lc "…"`); the train refuses `--apply` otherwise. Export `MMI_RELEASE_VERSION=X.Y.Z` only for a target the tag math cannot derive. A breaking signal in the range (`feat!:`, `BREAKING CHANGE:`) makes the train refuse until shimmed (patch) or declared a major.
|
|
31
31
|
|
|
32
|
+
## Bump rules
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
Patch is the default and needs nothing. `minor` only for a real feature or significant change, with a one-line reason exported as `MMI_BUMP_REASON`. `major` only with Jervaise's fresh approval in this turn: export `MMI_BUMP_REASON` and `MMI_MAJOR_APPROVED=<exact target version>` (e.g. `5.0.0`) only after that approval, never earlier or from a prior turn. The full versioning rules are in [docs/versioning.md](https://github.com/mutmutco/MMI-Hub/blob/development/docs/versioning.md).
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
## Latest Release
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
Verify Latest with the typed App-pool read (GitHub's Latest: never a draft or prerelease); a failed or empty read leaves Latest unverified: `mmi-cli devops api get repos/{owner}/{repo}/releases/latest | node -e 'const r = JSON.parse(require("node:fs").readFileSync(0, "utf8")); if (!r.tag_name || r.tag_name !== process.argv[1] || r.draft || r.prerelease) throw new Error("Latest is not the resolved tag"); console.log(r.tag_name, r.published_at);' "<resolved-tag>"`.
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
## Local checks
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Run from the primary checkout on the lane's start branch (`rc`; `development` for direct-track and `--dev`). A Jerv-Hub release on Windows must run under Git Bash (`"C:/Program Files/Git/bin/bash.exe" -lc "…"`) — the train refuses `--apply` before tagging when it is not. Export the bump intent once from the bare argument — `MMI_BUMP_INTENT=minor|major|patch`, unset → `patch`; `MMI_RELEASE_VERSION=X.Y.Z` only for an exact target the tag math cannot derive.
|
|
44
|
-
|
|
45
|
-
Two cases need a summary file. (1) **MMI-Hub** — always: write a fresh 3–6 line neutral summary to `f=$(mkdir -p .jerv/tmp && mktemp .jerv/tmp/release-summary.XXXXXX)` — sourced from the range `origin/main..origin/development`, rewritten in Hub-subsystem terms, never a product or brand name, and never a Jerv-side project (the train refuses such a line). Hub scope is only `mutmutco/MMI-Hub`: never a product's board or a product's deploy state. **Build and verify every line from ONE command's output**, never from commit subjects or PR titles alone: `git log --stat --format='%h %s%n%b' origin/main..origin/development` gives each commit's subject, its full body (where a bundled PR records `Closes #N`) and the files it changed in a single pass. A line whose claim you cannot point to in that output does not go in the file, and every `#N` a Hub line cites must appear there: the train refuses `--apply` on a citation that ships in no commit of the cut. (2) **Any product repo whose META carries `releaseChannel`** (`mmi-cli oracle org project get {owner}/{repo} --json`) — required too: read `releaseLanguage` (default `en`) and write 3–6 lines IN THAT LANGUAGE, in plain words for the project's audience: what changed and why it matters to a user; no commit prefixes, no issue or PR numbers, no file names, no product-internal jargon. The train refuses `--apply` without the file, and raw release notes are never posted to a project channel. A repo with no `releaseChannel` announces nothing, but an mm-work suite repo still requires the summary for its GitHub Release. An mm-work suite repo's summary follows the update-notes template below instead of the 3–6 line rule.
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
mkdir -p .jerv/tmp
|
|
49
|
-
mktemp .jerv/tmp/release-receipt.XXXXXX
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Scratch lives under `.jerv/tmp` in every repo: a repo-root `tmp/` may not exist at all, and an agent host guards the primary checkout against root writes outside `.jerv/tmp` — either one aborts the release before its first command runs.
|
|
53
|
-
|
|
54
|
-
Copy the returned pathname into `<result-path>` below; do not rely on shell variables surviving another tool call. For a product without a release channel:
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
mmi-cli devops release --apply --watch --json --out "<result-path>"
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
mmi-cli devops release --apply --watch --announce-summary-file "<summary-path>" --json --out "<result-path>"
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Add `--dev` for a full-track dev → main release. Keep `--watch` to block on the deploy/publish runs. `mmi-cli devops release --apply --ack <sha>[,<sha>…]` only when Jervaise has verified that a main-only commit the hotfix-coverage guard refused is already in the candidate — never ack to save time. The one command merges, runs the version fold (automatic, inside `mmi-cli devops release --apply`) that bumps the manifests unconditionally before the tag, pushes the tag first (`gate.yml` runs on `v*` tags, so the fold commit earns its required checks), waits for the required contexts, pushes `main`, publishes the Release, dispatches or correlates the deploy (`tenant-deploy.yml` only for tenant-container), announces only after the deploy and publish runs are green (the org alerts channel for the Hub; the project's own release channel for a product repo), re-syncs project info, and rolls `development` and `rc` forward. Independent legs run at the same time: deploy and publish are watched together, and once both settle the announcement, the alignment wait and the served-channel legs overlap; a `workflowRuns` row joined that way carries `parallel: true` beside its own conclusion. Nothing here is done by hand.
|
|
65
|
-
|
|
66
|
-
Describe the release in plain words before each command: “Preparing release”, “Waiting for checks”, “Waiting for publishing”, or “Finishing the existing release”. Keep temporary-file preparation separate from the long-running release command so its tool title cannot become a temporary filename; carry the returned path explicitly into the release command when tool calls do not share shell variables. Keep stderr visible: the CLI prints `Release: ` stages and elapsed updates every 30 seconds during long operations, while JSON and `--out` remain the verification record. Never redirect both streams into the result file.
|
|
67
|
-
|
|
68
|
-
Use the actual current stage, never a guessed sequence. Explain a pending result as “Publishing is still pending” or name the unfinished step, then narrate the sanctioned resume command as “Checking the remaining release steps”. Say “Release complete” only after the status fields prove every required follow-up complete. Temporary filenames, `XXXXXX`, receipts, and ledger folding are internal bookkeeping, never a user-facing status.
|
|
69
|
-
|
|
70
|
-
- `workflowRuns` — every run on the release SHA (deploy-model runs, any `push: main` deploy, the repo's own `gate`). On this host, discover them with the bounded run-list read below; filter locally by the exact receipt SHA. If the list hits its 100-row cap or returns no matching SHA, treat the run set as unverified and stop rather than infer completeness. Watch each matching non-success entry to conclusion: `mmi-cli devops read run watch <run-id> --repo {owner}/{repo} --exit-status --interval 60`. Name which run is red: `deploy.yml` / `publish.yml` / `tenant-deploy.yml` / `jerv-gateway` is a deploy or publish verdict; a `gate` push run is ordinary CI sharing the SHA.
|
|
71
|
-
- With `--watch`, require every follow-up complete before declaring the cut done. For any pending ledger leg, read [recovery.md](recovery.md) before continuing or starting a new train.
|
|
72
|
-
- `announceNote` — `announced` (to the alerts channel for the Hub, to the project release channel for a product repo), `skipped`, `not announced` (deploy or publish not green; the note says whether a `--resume` carrying the same `--announce-summary-file` will post it), or the failure note. The channel id itself is never printed.
|
|
73
|
-
- `devRollForward` / `rcAlignment` — `pushed`, or `pr-pending` with the alignment PR to land by true merge (Merge floor). An enqueued auto-merge is not evidence of the method; before reporting, read the enqueued method back — `autoMergeRequest.mergeMethod` from `mmi-cli devops read pr view <n> --repo {owner}/{repo} --json autoMergeRequest` — and prove it is `MERGE`. An enqueued `SQUASH` is a stop under the Merge floor, not something to wait out.
|
|
74
|
-
- `versionFold`, `rcRetirement`, `checkout` — `returned`, or the named reason you are still on `main`.
|
|
75
|
-
- `localInstall` (MMI-Hub) — the train installs the release on this machine via `mmi-hub update`; never run `npm i -g`.
|
|
76
|
-
For a private npm surface, read [verification.md](verification.md) before interpreting authentication or package visibility.
|
|
77
|
-
|
|
78
|
-
Then verify Latest with the typed App-pool read (GitHub's Latest: never a draft or prerelease); a failed or empty read leaves Latest unverified: `mmi-cli devops api get repos/{owner}/{repo}/releases/latest | node -e 'const r = JSON.parse(require("node:fs").readFileSync(0, "utf8")); if (!r.tag_name || r.tag_name !== process.argv[1] || r.draft || r.prerelease) throw new Error("Latest is not the resolved tag"); console.log(r.tag_name, r.published_at);' "<resolved-tag>"`.
|
|
42
|
+
- A PowerShell ancestry probe (`git merge-base --is-ancestor <a> <b>`) prints nothing either way: read `$LASTEXITCODE` (`0` = ancestor, `1` = not), never a blank result.
|
|
43
|
+
- `mmi-cli doctor` and `mmi-cli doctor --no-repo-writes` repair plugin wiring only and never touch the repository. Record the stale worktrees or approval rows they report as found; claim a cleanup only when `mmi-cli doctor --apply` or the host actually performed it.
|
package/skills/secrets/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: secrets
|
|
3
|
-
description: Manage the project vault and granted org-infra secrets.
|
|
3
|
+
description: Manage the project vault and granted org-infra secrets. Use to declare, set, rotate or consume a secret, not to read a value or edit Actions secrets.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
**Host-native invocation:** Claude `/mmi:secrets` · Codex `$mmi:secrets` · jervcode `/secrets` · OpenBot the `secrets` skill (loaded by name). A backticked `/name` in this doc names the matching workflow (this skill or a sibling), not a literal command.
|
|
@@ -12,7 +12,7 @@ description: Manage the project vault and granted org-infra secrets.
|
|
|
12
12
|
- **YOUR REPO** — `/mmi-future/<slug>/<KEY>` (stageless canonical, one value for every stage, the path deploys resolve) plus `/mmi-future/<slug>/{dev,rc,main}/*` (per-stage overrides). A staged `dev/<KEY>` WINS for that stage at deploy; `set`/`use` warn (names only) when an override shadows the canonical. The `dev`/non-`dev` `tier` field in older JSON is compatibility metadata, not an authority boundary.
|
|
13
13
|
- **ORG-INFRA** — `/mmi-future/{shared,cloudflare,docs,mmi-hub}/*` at every tier, plus the provider masters under `_org/<provider>/*` (e.g. `hetzner/HETZNER_MASTER_SSH_PRIVATE_KEY`, a whole-account credential). Master-only; a project-admin reaches one only via a master **grant**. For grants (including read-only wildcards), read [reference.md](reference.md) first.
|
|
14
14
|
|
|
15
|
-
**Declare-first:** the registry catalog is the SSOT; SSM is its projection. A `set` to an undeclared coordinate is rejected (the error names the path and fix); no master bypass. Declare with `mmi-cli
|
|
15
|
+
**Declare-first:** the registry catalog is the SSOT; SSM is its projection. A `set` to an undeclared coordinate is rejected (the error names the path and fix); no master bypass. Declare with `mmi-cli vault secrets declare <KEY> --purpose <text> --group <text>` (project-admin self-declare for your own repo; metadata only, never a value; no `--stages` = stageless canonical, `--stages dev` = a per-stage override), then retry. See declared keys with `mmi-cli vault secrets list`; ask for a missing key with `mmi-cli vault secrets request <KEY>`. `rm` of an undeclared path stays allowed. Google OAuth is one stageless pair at the slug root, bare `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` (`mmi-cli vault org oauth set-creds` writes them; the staged shape is retired).
|
|
16
16
|
|
|
17
17
|
All ops run through `mmi-cli vault secrets …`, which calls the org backend with the caller's `gh` token; the backend re-verifies project-admin and namespace and does the scoped SSM op. This skill never touches AWS.
|
|
18
18
|
|
|
@@ -24,7 +24,7 @@ mmi-cli vault secrets list # names + tier + * on those you can write; never v
|
|
|
24
24
|
|
|
25
25
|
`secrets: no registry META` or `Hub API unreachable` → repo unregistered, GitHub auth missing, or Hub down. Run `mmi-cli oracle org project get <owner/repo>` to tell which; a master-admin backfills the registry.
|
|
26
26
|
|
|
27
|
-
**Before escalating to the owner's console, look in the org vault.** A provider-wide or account-level question (every project, every volume, the whole account) is answered by the provider master key, not by the console and not by a narrower new grant: check `mmi-cli
|
|
27
|
+
**Before escalating to the owner's console, look in the org vault.** A provider-wide or account-level question (every project, every volume, the whole account) is answered by the provider master key, not by the console and not by a narrower new grant: check `mmi-cli oracle org access capabilities` (every credential name, tier and scope you can reach, org-infra included; `catalog` and `find` are master-only) for `_org/<provider>/*`, then consume it with `mmi-cli vault secrets use <provider>/<KEY> --slug _org -- <cmd>`. Escalate to the owner's console, or ask for one scoped key, only when that view shows no such master key.
|
|
28
28
|
|
|
29
29
|
## Step 1 — the verb
|
|
30
30
|
|
|
@@ -32,12 +32,13 @@ Current repo by default; `--repo owner/Name` targets another (you must be its pr
|
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
mmi-cli vault secrets use SCRAPER_API_KEY -- <cmd> # consume keyless: injected into env, never printed
|
|
35
|
-
|
|
35
|
+
<command that prints the value> | mmi-cli vault secrets set SCRAPER_API_KEY # write/rotate: pipe from the value's source
|
|
36
36
|
mmi-cli vault secrets verify RECALL_API_KEY # validate a known provider key
|
|
37
37
|
mmi-cli vault secrets rm SCRAPER_API_KEY
|
|
38
|
+
mmi-cli vault secrets list # readback after set: the name shows at the intended tier
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
There is no value argument
|
|
41
|
+
There is no value argument, and the value never sits in a shell variable, a file or the command line: pipe it from where it lives. Confirmation prints name and tier only; confirm every `set` with the `list` readback (bare `<KEY>` = stageless canonical, `dev/<KEY>` = override). On Windows, read [reference.md](reference.md) before wrapping a multiline command. For rotation, org-infra elevation, new-key coordinates, or tier-to-tier copies, read [reference.md](reference.md) first.
|
|
41
42
|
|
|
42
43
|
Runtime consumes declared keys through its scoped broker token (central deploy injects the declared stage set, no repo `.env`); CI reads keylessly through its OIDC role. Treat every secret as write-once.
|
|
43
44
|
|
|
@@ -7,11 +7,11 @@ instead of forty. A wildcard never confers write; asking for one as `rw` is refu
|
|
|
7
7
|
|
|
8
8
|
**Windows: a multiline wrapped command must be file-backed (#6048).** `cmd.exe` truncates at the first
|
|
9
9
|
newline, so an inline `node -e "<multiline script>"` after `--` reaches the child truncated and fails
|
|
10
|
-
before your code runs. Write the script to a **project-local ignored file** (e.g.
|
|
10
|
+
before your code runs. Write the script to a **project-local ignored file** (e.g. `.jerv/tmp/fetch-models.mjs`
|
|
11
11
|
— git-ignored, never tracked) and wrap the file instead; the key is still injected into the child's env:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
mmi-cli vault secrets use GEMINI_API_KEY -- node tmp/fetch-models.mjs
|
|
14
|
+
mmi-cli vault secrets use GEMINI_API_KEY -- node .jerv/tmp/fetch-models.mjs
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Rotation checklist
|
|
@@ -36,10 +36,10 @@ those keys asks the master, who grants a **scoped, auditable** standing access t
|
|
|
36
36
|
it). These verbs are **master-only** — the backend 403s anyone else.
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
# MASTER: let
|
|
40
|
-
mmi-cli vault secrets grant mutmutco/MM-Chat
|
|
39
|
+
# MASTER: let @<login> consume one _org provider key from their MM-Chat project
|
|
40
|
+
mmi-cli vault secrets grant mutmutco/MM-Chat <login> google/SOME_SHARED_KEY
|
|
41
41
|
# MASTER: withdraw it
|
|
42
|
-
mmi-cli vault secrets revoke mutmutco/MM-Chat
|
|
42
|
+
mmi-cli vault secrets revoke mutmutco/MM-Chat <login> google/SOME_SHARED_KEY
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
The master can also operate the org-infra key directly while guiding (master ⊇ project-admin). Org-infra
|
|
@@ -64,45 +64,3 @@ mmi-cli vault secrets copy --from rc --to dev --keys RECALL_API_KEY,GEMINI_API_K
|
|
|
64
64
|
mmi-cli vault secrets copy --from rc --to dev --keys RECALL_API_KEY --dry-run # plan only
|
|
65
65
|
```
|
|
66
66
|
Prefer this over manual copy piping — audit-logged, blocklist enforced.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
## Detail moved from SKILL.md (verbatim)
|
|
71
|
-
|
|
72
|
-
**Authority:** a project-admin self-serves their own product repo's full vault tree (`mmi-cli oracle org access
|
|
73
|
-
role` → `project-admin` + `train`): stageless, `dev`, `rc`, and `main`. Do not redirect them to master for
|
|
74
|
-
an own-project coordinate. Only org-infra grants and cross-project administration stay master-only.
|
|
75
|
-
|
|
76
|
-
A bare `<KEY>` is the **stageless canonical** at the slug root — one value every stage shares (#2244)
|
|
77
|
-
and the path deploys resolve (#2523). A staged `dev/<KEY>` is a **per-stage override** and WINS for that
|
|
78
|
-
stage at deploy (#2522); `set`/`use` warn (names only) when an override shadows the canonical. The
|
|
79
|
-
`dev`/non-`dev` `tier` field in older JSON is compatibility metadata, not an authority boundary: an
|
|
80
|
-
own-project `main/SECRET_KEY_BASE` or `rc/DB_URL` remains project-admin self-service.
|
|
81
|
-
|
|
82
|
-
**Declare-first (#2528):** the registry catalog is the SSOT; SSM is a projection of it. A `set` to a
|
|
83
|
-
coordinate not declared in the catalog is **rejected** — the error names the attempted path and the fix.
|
|
84
|
-
Declare the key first via `mmi-cli oracle org project set <owner/repo> --secrets-file <catalog.json>` (`stages: []`
|
|
85
|
-
= the shared stageless canonical, `stages: ["dev"]` = a per-stage override), then retry. See what is
|
|
86
|
-
declared with `mmi-cli vault secrets catalog` or `secrets list`; ask for a key you lack via `mmi-cli vault secrets
|
|
87
|
-
request <KEY>`. There is no master bypass. `rm` of an undeclared path stays allowed, so cleanup keeps
|
|
88
|
-
working. Google OAuth is one stageless pair per repo: bare `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET`
|
|
89
|
-
at the slug root (the staged `{dev,rc,main}/GOOGLE_*` shape is retired; `org oauth set-creds` writes the
|
|
90
|
-
bare keys).
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
# CONSUME a secret keyless — injected into the command's env, NEVER printed (raw `secrets get` was
|
|
94
|
-
# removed, the floor wins, #2844):
|
|
95
|
-
mmi-cli vault secrets use SCRAPER_API_KEY -- <cmd>
|
|
96
|
-
|
|
97
|
-
**Never** pass a value as an argument (`secrets set KEY thevalue` is wrong — there is no value arg). The
|
|
98
|
-
confirmation prints the **name and tier only**, never the value.
|
|
99
|
-
|
|
100
|
-
- **Never echo a value** — not in chat, a commit, a log, or an issue. No command emits a value to stdout;
|
|
101
|
-
consume one keyless with `secrets use <KEY> -- <cmd>` (#2844). Treat every secret as write-once.
|
|
102
|
-
- Authority is **GitHub**: project-admin = repo `admin`, or repo `write`/`maintain` plus the registry `projectAdmins` entry; master =
|
|
103
|
-
org owner. The backend checks both with the org App token, so the decision is server-side (your token
|
|
104
|
-
scope can't widen it).
|
|
105
|
-
- Runtime consumes declared keys through its scoped broker token (and central deploy injects the declared
|
|
106
|
-
stage set without a repo `.env`); CI reads keylessly through its OIDC role. Neither uses raw `/secrets`
|
|
107
|
-
output. `secrets use <KEY>` is the safe local command-consumption path.
|
|
108
|
-
- Every self-service write is **attributable** — the backend logs actor + repo + KEY name (never the value).
|