@davidvornholt/standards 0.22.0 → 0.22.1
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/README.md +1 -1
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/creds-sops-structure.ts +2 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ standards poller --print-units --config <path>
|
|
|
29
29
|
|
|
30
30
|
`dependabot --write` regenerates the composed `.github/dependabot.yml` from the canonical `.github/dependabot.base.yml` and the optional repo-owned `.github/dependabot.local.yml`; `init` and `sync` do the same automatically. `dependabot --check` verifies the generated file still matches its sources, and `doctor`/`check` include the same verification. The overlay is deliberately lean and additive only: new update blocks for repo-specific ecosystems, top-level private registry definitions, and `ignore` or `registries` entries appended by repeating a canonical block's normalized target. Matching blocks cannot add labels, groups, cooldowns, pull-request limits, or other policy. Update blocks for the same ecosystem and target branch must not select intersecting directories after Dependabot's path normalization. A plural `directories` target is expanded as a glob when it contains `*`, `?`, or both `[` and `]`: `*` and bare `**` stay within one path segment, `**/` matches zero or more directory segments, `?` matches one non-separator character, and bracket expressions match character sets or ranges. Singular `directory` values are always literal.
|
|
31
31
|
|
|
32
|
-
`dev-env` composes each workspace's dev environment from three layers sharing one workspace shape — keyed by workspace group and a one-segment kebab-case workspace name (`apps.<name>`, `packages.<name>`): the tracked plain `config/dev.yaml`, the SOPS-encrypted `secrets/dev.yaml` (required, decrypted via sops), and the gitignored plain `config/dev.local.yaml`, applied in that order with later layers overriding per key. Secret-layer env values are strings; a plain-layer env value may be a string or the brokered reference described below. A key declared in both tracked shared layers is a validation problem — a value is either configuration or a secret — while a local override of either is the file's purpose. Plain layers are optional and may be comment-only; `config/dev.local.yaml` must itself be gitignored because it may override secret values. The command transactionally writes every declared workspace's `.env.local` with owner-only permissions and a do-not-edit header naming the contributing sources. It also discovers direct `apps/*` and `packages/*` directories containing `package.json` and removes a stale `.env.local` only when its first line is that exact header; hand-owned files, edited headers, nested directories, and symlinked paths are left untouched. Writes and removals commit or roll back as one transaction, preserving prior contents, modes, and absent files. The final files and the transaction's actual random `.env.local.standards-*.tmp` and `.env.local.standards-*.bak` paths must all be gitignored before staging starts. Existing consumers must add those two artifact patterns themselves because `.gitignore` is seeded only during `init`; `sync` does not change it. Its Bun-specific dotenv codec exactly round-trips every value it accepts without adding helper environment variables; a value the codec cannot encode exactly is gathered as a validation problem instead of being changed silently. Validation gathers all document, containment, destination-type, workspace, and gitignore problems before writing anything; symlink destinations, duplicate resolved destinations, changed parent-directory identities, and symlinked workspace paths are rejected without following the link. Cleanup trouble after a completed commit is reported loudly as a warning rather than falsely reporting generation failure. Parent identities are checked immediately before each path operation; an unavoidable swap in the syscall-sized interval after a check remains outside the non-hostile maintainer threat model. The canonical `justfile` exposes the command as `just dev-env-generate`, and `just dev-refresh` chains a `just secrets edit dev` session into regeneration. A plain configuration layer may declare a **brokered S3 pair reference** instead of a literal: an object value `{ brokeredS3: <secrets-target>, key: <dotted.key>, part: access_key_id | secret_access_key }` pointing at a credential pair `creds add cloudflare --s3` minted into another SOPS target. An existing target name must bind exactly one contained file, either `infra/hosts/<name>/secrets.yaml` or `secrets/<name>.yaml`; both files existing is an ambiguity error, never host preference. The SOPS-encrypted `secrets/dev.yaml` must authorize every referenced pair with its exact `<secrets-target>:<dotted.key>` string under the reserved top-level `brokeredReferences` list. Plain layers reject that reserved key, and the secrets layer rejects reference objects: configuration selects a pair while encrypted policy authorizes its release into plaintext `.env.local`. Resolution rejects an unauthorized pair with the exact allowlist entry to add before invoking SOPS on that target. It then requires both `access_key_id` and `secret_access_key` to be strings, even when the reference selects only one part. Resolution runs after layer composition, so a later layer's literal overrides an earlier layer's reference and a reference that lost the merge is never decrypted; each authorized referenced target is decrypted once per run, and a missing target, ambiguous target, missing or partial pair, or unencodable resolved value is gathered as a named validation problem without exposing secret values. The secret value therefore keeps exactly one home — the broker's ledger. The loop closes on the broker side: after `creds add` verifies an exact referenced pair write, and after `creds apply` verifies a renewal in one, the command regenerates the dev env files itself, so a rotated pair reaches every generated `.env.local` without a manual step. Refresh evidence is pair-granular: a bearer sibling in the same SOPS file cannot trigger rendering of an unsafe pair, and a verified S3 sibling updates while an unsafe pair keeps its prior generated lines. If those prior owned lines cannot be proven and preserved, the refresh fails without changing any env file; every refresh failure is reported after the durable SOPS write remains committed.
|
|
32
|
+
`dev-env` composes each workspace's dev environment from three declaration layers sharing one workspace shape — keyed by workspace group and a one-segment kebab-case workspace name (`apps.<name>`, `packages.<name>`): the tracked plain `config/dev.yaml`, the SOPS-encrypted `secrets/dev.yaml` (required, decrypted via sops), and the gitignored plain `config/dev.local.yaml`, applied in that order with later layers overriding per key. Effective values may also come from authorized broker-owned S3 pairs in separate SOPS targets referenced by either plain layer. Secret-layer env values are strings; a plain-layer env value may be a string or the brokered reference described below. A key declared in both tracked shared layers is a validation problem — a value is either configuration or a secret — while a local override of either is the file's purpose. Plain layers are optional and may be comment-only; `config/dev.local.yaml` must itself be gitignored because it may override secret values. The command transactionally writes every declared workspace's `.env.local` with owner-only permissions and a do-not-edit header naming the contributing sources. It also discovers direct `apps/*` and `packages/*` directories containing `package.json` and removes a stale `.env.local` only when its first line is that exact header; hand-owned files, edited headers, nested directories, and symlinked paths are left untouched. Writes and removals commit or roll back as one transaction, preserving prior contents, modes, and absent files. The final files and the transaction's actual random `.env.local.standards-*.tmp` and `.env.local.standards-*.bak` paths must all be gitignored before staging starts. Existing consumers must add those two artifact patterns themselves because `.gitignore` is seeded only during `init`; `sync` does not change it. Its Bun-specific dotenv codec exactly round-trips every value it accepts without adding helper environment variables; a value the codec cannot encode exactly is gathered as a validation problem instead of being changed silently. Validation gathers all document, containment, destination-type, workspace, and gitignore problems before writing anything; symlink destinations, duplicate resolved destinations, changed parent-directory identities, and symlinked workspace paths are rejected without following the link. Cleanup trouble after a completed commit is reported loudly as a warning rather than falsely reporting generation failure. Parent identities are checked immediately before each path operation; an unavoidable swap in the syscall-sized interval after a check remains outside the non-hostile maintainer threat model. The canonical `justfile` exposes the command as `just dev-env-generate`, and `just dev-refresh` chains a `just secrets edit dev` session into regeneration. A plain configuration layer may declare a **brokered S3 pair reference** instead of a literal: an object value `{ brokeredS3: <secrets-target>, key: <dotted.key>, part: access_key_id | secret_access_key }` pointing at a credential pair `creds add cloudflare --s3` minted into another SOPS target. An existing target name must bind exactly one contained file, either `infra/hosts/<name>/secrets.yaml` or `secrets/<name>.yaml`; both files existing is an ambiguity error, never host preference. The SOPS-encrypted `secrets/dev.yaml` must authorize every referenced pair with its exact `<secrets-target>:<dotted.key>` string under the reserved top-level `brokeredReferences` list. Plain layers reject that reserved key, and the secrets layer rejects reference objects: configuration selects a pair while encrypted policy authorizes its release into plaintext `.env.local`. Resolution rejects an unauthorized pair with the exact allowlist entry to add before invoking SOPS on that target. It then requires both `access_key_id` and `secret_access_key` to be strings, even when the reference selects only one part. Resolution runs after layer composition, so a later layer's literal overrides an earlier layer's reference and a reference that lost the merge is never decrypted; each authorized referenced target is decrypted once per run, and a missing target, ambiguous target, missing or partial pair, or unencodable resolved value is gathered as a named validation problem without exposing secret values. The secret value therefore keeps exactly one home — the broker's ledger. The loop closes on the broker side: after `creds add` verifies an exact referenced pair write, and after `creds apply` verifies a renewal in one, the command regenerates the dev env files itself, so a rotated pair reaches every generated `.env.local` without a manual step. Refresh evidence is pair-granular: a bearer sibling in the same SOPS file cannot trigger rendering of an unsafe pair, and a verified S3 sibling updates while an unsafe pair keeps its prior generated lines. If those prior owned lines cannot be proven and preserved, the refresh fails without changing any env file; every refresh failure is reported after the durable SOPS write remains committed.
|
|
33
33
|
|
|
34
34
|
`check` also rejects the raw token formed by `biome-` + `ignore` anywhere in lock-listed canonical files. The intentionally blunt policy keeps synced sources compatible with consumer Biome configurations without invoking Biome or maintaining language-aware comment parsing.
|
|
35
35
|
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -965,7 +965,7 @@ Commands:
|
|
|
965
965
|
doctor Validate extension seams only
|
|
966
966
|
structure Validate monorepo structure rules only
|
|
967
967
|
dependabot Verify (--check) or regenerate (--write) the composed .github/dependabot.yml
|
|
968
|
-
dev-env Compose each workspace's generated .env.local from
|
|
968
|
+
dev-env Compose each workspace's generated .env.local from its three dev layers and authorized broker-owned S3 pair references
|
|
969
969
|
github Compare (--check) or converge (--apply) live GitHub settings
|
|
970
970
|
creds Mint, rotate, and revoke brokered credentials (see \`standards creds help\`)
|
|
971
971
|
poller Run one fix-poller tick over the configured repositories (host automation)
|
|
@@ -104,7 +104,8 @@ const collectLeaves = (
|
|
|
104
104
|
keys: Array<string>,
|
|
105
105
|
): string | null => {
|
|
106
106
|
if (isSeq(node)) {
|
|
107
|
-
|
|
107
|
+
// Broker destinations use mapping-only paths, so arrays have no brokered leaves.
|
|
108
|
+
return null;
|
|
108
109
|
}
|
|
109
110
|
if (isAlias(node)) {
|
|
110
111
|
return `aliases are not supported at ${prefix.join('.')}`;
|