Implement profiles.json v2 config parser with validation invariants #103

Closed
opened 2026-07-02 17:37:00 -05:00 by sysadmin · 0 comments
Owner

Summary

Implement support for profiles.json version 2 using the agreed environment → service → identity hierarchy from Issue #100.

Canonical profile address:

{environment}.{service}.{identity}

Examples:

prgs.gitea.author
prgs.gitea.reviewer
mdcps.gitea.author
mdcps.gitea.reviewer
mdcps.jenkins.reader
mdcps.glitchtip.reader

Source discussion

Refs #100

Scope

Add config-loader support for:

  • version: 2
  • top-level environments
  • per-environment services
  • per-service identities
  • aliases
  • service-level defaults inherited by identities
  • keychain-only auth references
  • fail-closed validation

Required validation invariants

The loader must fail closed on:

  • unknown config version
  • missing required version
  • malformed environment/service/identity structure
  • unknown or ambiguous profile selector
  • conflicting alias/dotted path selector
  • TBD-* usernames
  • reviewer identities that can create PRs or push branches
  • operations that cannot be normalized safely
  • missing auth reference
  • auth entries containing inline secrets

Reviewer-identity deadlock rule

Any identity allowed to perform either:

  • gitea.pr.approve
  • gitea.pr.merge

must explicitly forbid:

  • gitea.pr.create
  • gitea.branch.push

This prevents the PR #102-style deadlock where the reviewer identity creates the PR and then cannot independently review it.

Backward compatibility

Existing v1 profiles must continue to resolve through aliases or v1 compatibility loading:

  • mdcps
  • prgs-author
  • prgs-reviewer

Resolution order should be strict:

  1. exact alias
  2. exact dotted path
  3. fail closed

No fuzzy matching.

Non-goals

  • Do not implement migration writing in this issue.
  • Do not rename keychain items.
  • Do not implement Jenkins or GlitchTip tools.
  • Do not create new service credentials.
  • Do not change release/tag state.

Acceptance criteria

  • v1 config still loads.
  • v2 config loads.
  • aliases resolve correctly.
  • dotted paths resolve correctly.
  • ambiguous selectors fail closed.
  • unknown versions fail closed.
  • missing version fails closed.
  • TBD-* usernames fail closed.
  • reviewer-deadlock invariant is enforced.
  • inline secret values are rejected.
  • service defaults inherit correctly.
  • malformed non-selected service subtrees do not unnecessarily block unrelated service startup if the chosen runtime only needs one service subtree, unless the final design says full-file validation is required.
  • tests cover happy path and fail-closed cases.
## Summary Implement support for `profiles.json` version 2 using the agreed environment → service → identity hierarchy from Issue #100. Canonical profile address: ```text {environment}.{service}.{identity} ``` Examples: ```text prgs.gitea.author prgs.gitea.reviewer mdcps.gitea.author mdcps.gitea.reviewer mdcps.jenkins.reader mdcps.glitchtip.reader ``` ## Source discussion Refs #100 ## Scope Add config-loader support for: * `version: 2` * top-level `environments` * per-environment `services` * per-service `identities` * `aliases` * service-level defaults inherited by identities * keychain-only auth references * fail-closed validation ## Required validation invariants The loader must fail closed on: * unknown config version * missing required `version` * malformed environment/service/identity structure * unknown or ambiguous profile selector * conflicting alias/dotted path selector * `TBD-*` usernames * reviewer identities that can create PRs or push branches * operations that cannot be normalized safely * missing auth reference * auth entries containing inline secrets ## Reviewer-identity deadlock rule Any identity allowed to perform either: * `gitea.pr.approve` * `gitea.pr.merge` must explicitly forbid: * `gitea.pr.create` * `gitea.branch.push` This prevents the PR #102-style deadlock where the reviewer identity creates the PR and then cannot independently review it. ## Backward compatibility Existing v1 profiles must continue to resolve through aliases or v1 compatibility loading: * `mdcps` * `prgs-author` * `prgs-reviewer` Resolution order should be strict: 1. exact alias 2. exact dotted path 3. fail closed No fuzzy matching. ## Non-goals * Do not implement migration writing in this issue. * Do not rename keychain items. * Do not implement Jenkins or GlitchTip tools. * Do not create new service credentials. * Do not change release/tag state. ## Acceptance criteria * v1 config still loads. * v2 config loads. * aliases resolve correctly. * dotted paths resolve correctly. * ambiguous selectors fail closed. * unknown versions fail closed. * missing version fails closed. * `TBD-*` usernames fail closed. * reviewer-deadlock invariant is enforced. * inline secret values are rejected. * service defaults inherit correctly. * malformed non-selected service subtrees do not unnecessarily block unrelated service startup if the chosen runtime only needs one service subtree, unless the final design says full-file validation is required. * tests cover happy path and fail-closed cases.
sysadmin added the mcpsecurityworkflowenhancement labels 2026-07-02 17:38:15 -05:00
sysadmin added the status:in-progress label 2026-07-02 17:41:25 -05:00
sysadmin removed the status:in-progress label 2026-07-02 18:47:28 -05:00
Sign in to join this conversation.