Discussion: profiles.json v2 model for multi-service environments #100
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Discussion: profiles.json v2 model for multi-service environments
Background
The current
~/.config/gitea-tools/profiles.jsonmodel is too flat and Gitea-specific.Current shape is roughly:
profiles.mdcpsprofiles.prgs-authorprofiles.prgs-reviewerThis worked for Gitea-only workflows, but we now need to support multiple environments and multiple services.
Real environments
PRGS / local server environment
MDCPS environment
Problem
The current JSON mixes several concepts into one flat profile object:
Before we add Jenkins and GlitchTip credentials, we should agree on the next config model.
Proposed direction
Move to a versioned
profiles.jsonv2 model with a three-level hierarchy:Canonical profile address:
Examples:
Old flat names would continue through aliases:
Security requirements
whoamiidentity must remain the source of truth.forbidden_operationsmust always overrideallowed_operations.allowed_operationsshould continue to fail closed unless explicitly changed.Proposed keychain naming convention
Existing keychain IDs can continue to work through explicit
auth.idreferences. Renaming existing keychain items should be optional/lazy.Example v2 shape
Proposed migration strategy
version: 1files supported.version: 2.mdcpsprgs-authorprgs-reviewerAreas likely affected if approved
Open questions for review
mdcpsalias map tomdcps.gitea.author, or should it stay deny-all until the second user is ready?MCP_ENV,MCP_SERVICE, andMCP_IDENTITY?auth.id?whoamiexpose safe metadata likeenvironment,service, andidentity?gitea.pr.merge, or should backward-compatible unqualified operations likemergecontinue internally?Proposed acceptance for this discussion
This issue can close only after reviewers agree on:
No implementation should begin until this discussion reaches a decision.
Reviewers and other LLM sessions: please comment directly on this issue with your recommendation per open question. Discussion only — no implementation, branches, or PRs until this reaches a decision.
Recommendation on profiles.json v2
Summary
The proposed v2 three-level hierarchy (
environment->service->identity) is a solid and necessary design to scale the Control Plane beyond Gitea. It cleanly separates identity roles, isolates service-specific parameters, and scales gracefully. I recommend proceeding with the design with a few minor improvements around environment variables and backward-compatibility maps.Answers to open questions
mdcpsalias: Mapmdcpsdirectly tomdcps.gitea.authorfor backward-compatibility. Do not make it deny-all, as this would break existing workflows; instead, print a deprecation warning in the runtime logs.sysadmin(similar to the PRGS environment) for consistency, or provisionmdcps-revieweras the dedicated reviewer account.profiles.jsonv2) to prevent configuration drift and simplify deployment orchestration, but allow service-specific env overrides (GITEA_MCP_CONFIG,JENKINS_MCP_CONFIG) for modular developers.MCP_ENV,MCP_SERVICE,MCP_IDENTITY) to enable stateless orchestrators (like containerized runners) to inject roles dynamically.auth.idmapping. Forcing immediate renaming causes user friction, but the migration tool should actively recommend the new dotted convention (mdcps.gitea.author.token) for new enrollments.whoamimetadata: Yes, exposing safe metadata (environment,service,identity) inwhoamioutputs helps debug multi-agent handoffs and orchestrator pathing without exposing any credentials.gitea.pr.merge). Unqualified legacy operations (likemerge) should be lazily translated internally for backward compatibility but deprecated in documentation.Risks / concerns
glitchtipdoes not block Gitea tool startup.Suggested changes to the proposed model
default_ownerordefault_repois defined at the environment-service level (e.g.environments.prgs.services.gitea.default_owner), allow identities to inherit them unless overridden.Implementation readiness
Ready with changes
Controller handoff summary
Recommendation on profiles.json v2
Summary
I support the v2
environment.service.identitymodel, but I would tighten the default behavior around incomplete identities and service isolation before implementation. The model should preserve backward compatibility for existing Gitea workflows while making every ambiguous selector fail closed, keeping service credentials isolated by runtime, and using namespaced operations as the canonical authorization language.Answers to open questions
mdcpsalias only if it is explicitly treated asmdcps.gitea.authorand never gains review/merge permissions. If there is any chance existing callers assumemdcpscan do reviewer/merger work, make the alias deny-all untilmdcps.gitea.revieweris provisioned. My preference is:mdcps->mdcps.gitea.author, with a deprecation warning and author-only gates.913443, verified bywhoami, and it should not share credentials with the author identity. Do not enable approve/merge for MDCPS until that username is known and tested.gitea-mcpshould not even be handed Jenkins or GlitchTip credential references.mdcps.gitea.author). Generic selectors are useful for process startup, but they should resolve deterministically to the same dotted path. I would supportMCP_PROFILE=mdcps.gitea.authorfirst, plus optionalMCP_ENV,MCP_SERVICE, andMCP_IDENTITYonly as structured inputs that must compose to exactly one profile or fail closed.auth.idsupport indefinitely for compatibility. New generated profiles should use the dotted naming convention, and a later dry-run migration helper can suggest renames without reading or modifying secret values.whoamishould expose safe metadata:environment,service,identity,profile_path,execution_profile,audit_label, resolved server/base URL, and verified authenticated username where the service supports it. It must not expose token values, raw keychain IDs unless already considered non-secret config, or raw auth errors.gitea.pr.merge,jenkins.build.read,glitchtip.event.read. Backward-compatible unqualified operations such asmergeorreadcan be accepted only through an explicit v1 compatibility map after the service is known. Internally, gates should normalize to namespaced operations before authorization checks.Risks / concerns
The largest risk is that aliases and generic selectors create accidental privilege expansion.
mdcpsmust never silently become a reviewer/merger selector. The second risk is credential-reference sprawl: one shared JSON file is convenient, but deployed service processes should still receive only the subset of config needed for their trust boundary. Finally, operation-name compatibility needs tests; otherwise old unqualified names could bypass the intended namespaced deny rules.Suggested changes to the proposed model
Add a top-level
default_profileonly if it can benullor deny-all by default; do not infer one from the first configured identity. Add a canonicalprofile_pathfield in resolved profile output so audit logs andwhoamican report the exact selectedenvironment.service.identity. Add an explicitcompat_aliasesorlegacy_aliasesblock separate from normal aliases, with deprecation metadata and target service restrictions. Add JSON Schema validation for v2 and tests for: missingallowed_operations, forbidden-overrides-allowed, alias resolution, dotted path resolution, generic selector composition, unknown service, and v1 compatibility mapping.Implementation readiness
Ready with changes
Controller handoff summary
Recommendation on profiles.json v2
LLM review feedback for discussion. Not an owner decision.
Summary
The three-level
environment.service.identitymodel is right and matches the trust-boundary architecture (one MCP server per boundary, per-service credentials, deny-by-default). Recommend adopting it with changes: add a config-load invariant that reviewer/merger identities cannot create PRs (prevents the #102 deadlock), refuseTBD-*usernames at load, define operation-name normalization before enforcing forbidden-overrides-allowed, and make the dotted path the single canonical selector.Answers to open questions
mdcpsalias →mdcps.gitea.author(not deny-all). Aliases exist for backward compatibility; breaking the working mdcps author flow buys no safety because merge/approve are already in that identity'sforbidden_operations. Merge in MDCPS stays naturally impossible until the reviewer identity exists — that is the correct fail-closed shape. Deny-all would just push users to work around the config.svc-gitea-review, mirroringsvc-jenkins-read), never the same login as the author identity, with only reviewer-side permissions. Until provisioned, keepTBD-second-mdcps-user— and the loader should refuse to activate any identity whose username matchesTBD-*(explicit fail-closed, not a silent broken profile).environment.servicesubtree and refuses to read credentials for any other service. Revisit file-splitting only if the file becomes unmanageable (anincludemechanism can come later; don't build it now).MCP_PROFILE=prgs.gitea.reviewer(or the existing per-service var) is the one true selector and the name that appears in audit logs.MCP_ENV/MCP_SERVICE/MCP_IDENTITYmay be supported as a convenience that must resolve to exactly one dotted address; if both forms are set and disagree → fail closed with a clear error. Never allow partial selectors to default silently.auth.id; rename nothing now. New entries adopt theenv.service.identity.tokenconvention. A migration helper can come later (reads v1, writes v2, backup, dry-run default, never touches keychain secrets — as the issue already proposes). Mass-renaming live secrets is pure risk, zero security gain.whoamishould exposeenvironment,service,identity,role,profile_name,allowed_operations, and the auth source type (keychain/env) — never the token and preferably not the keychain item id. This directly helps the #102 deadlock: a session can see "I am the reviewer identity" before it mistakenly creates a PR. (Precedent:gitea_whoamialready returns profile metadata safely.)gitea.pr.merge), unqualified accepted as deprecated aliases. Define a single normalization table (merge→gitea.pr.mergein a Gitea-service context); enforcement compares post-normalization, so a legacyforbidden: ["merge"]still blocksgitea.pr.merge. Unknown/unmappable operation names fail closed. Emit a deprecation note when an unqualified name is used so configs converge on namespaced form.mdcps.jenkins.trigger) with its own gated approval — never added to thereaderidentity.Reviewer-identity deadlock note
Document and enforce in both places:
allowed_operationsincludegitea.pr.approveorgitea.pr.mergeMUST havegitea.pr.createandgitea.branch.pushinforbidden_operations. Config validation refuses to load a profile violating this. The draft'sprgs.gitea.reviewerexample already has exactly this shape — promote it from example to rule.sysadmin/prgs-reviewerMCP session;sysadminbecame the author and could not review it).Enforcement in config + explanation in docs; neither alone is sufficient.
Risks / concerns
Suggested changes to the proposed model
TBD-*usernames (fail closed with a clear provisioning message).versionfield; unknown version → fail closed.roleecho towhoamisafe metadata (question 6 list).Implementation readiness
Ready with changes — the six suggested changes above, plus owner decisions on open questions 2 (MDCPS reviewer username) and home of the implementation (this repo vs a shared control-plane config library — the issue's own final acceptance item, still open).
Controller Handoff Summary
Work performed
Reviewed the full profiles.json v2 proposal on #100 and posted this recommendation comment answering all 8 open questions plus the PR #102 reviewer-identity deadlock follow-up.
Current state
Scaled-Tech-Consulting/Gitea-Tools, master790c2c8, unmodifiedFiles changed
None.
Validation
Not applicable — discussion only.
Issues encountered
None.
Review needed?
No review needed — discussion/comment only. Owner/design feedback needed on the readiness call and the two remaining owner decisions.
Next recommended action
Owner: provision the second MDCPS Gitea reviewer account (question 2), decide implementation home (this repo vs shared config library), and confirm/adjust the six suggested changes. Then #100 can close per its acceptance list and an implementation issue can be opened.
Safety confirmations
Controller synthesis for profiles.json v2
Current consensus
Reviewers agree that the proposed v2 three-level hierarchy (
environment->service->identity) is the correct architectural direction. The following decisions appear settled:mdcpsAlias: Map it tomdcps.gitea.authorfor backward-compatibility (relying onforbidden_operationsfor gating).profiles.jsonv2) to prevent configuration drift.auth.idmapping; new keychain items should follow the dotted convention.whoamiMetadata: Expose safe metadata (environment,service,identity,role,profile_name,allowed_operations,authsource type) to help tools and orchestrators detect identity states.gitea.pr.merge), translating unqualified legacy operations internally and marking them deprecated.forbidden_operations, and update workflow docs to explicitly warn against using reviewer identities to create PRs.Decisions still needed from owner
svc-gitea-revieworsysadmin) for reviewer/merge workflows in MDCPS.MCP_ENV,MCP_SERVICE,MCP_IDENTITY) alongside the canonical dotted path (MCP_PROFILE). Recommendation is that dotted path is canonical, selectors are optional sugar, and any conflict fails closed.Gitea-Tools) or in a shared Control Plane config library.Recommended v2 direction
Implement the versioned
profiles.jsonv2 model with theenvironment -> service -> identityhierarchy, dotted paths (e.g.prgs.gitea.author) as the primary selector, and aliases for backward-compatibility. Include strict config-level invariants that block reviewer accounts from creating PRs and refuse to loadTBD-*placeholders or unrecognized schema versions.Proposed implementation issues after owner approval
TBD-*users, and validate the reviewer deadlock invariant).gitea_whoamiand execution profiles to output namespaced roles, allowed/forbidden lists, and service scopes).Risks / blockers
Owner decision checklist
Controller Handoff Summary
Work performed
Synthesized the consensus, open questions, recommended shape, and migration plan from Issue #100 and comment #1613 into a structured Controller Synthesis.
Current state
Scaled-Tech-Consulting/Gitea-Tools, master790c2c8, cleanFiles changed
None.
Validation
Not applicable — discussion synthesis only.
Issues encountered
None.
Review needed?
Owner decision needed.
Next recommended action
Owner reviews the decisions checklist, chooses the implementation home and reviewer account, and moves #100 to implementation-ready state.
Safety confirmations
Implementation issues created from discussion
Created the following follow-up issues from the converged
profiles.json v2discussion:Notes:
config/implementation/migration/tests/mdcps/blockeddo not exist; closest existing labels were applied and no new labels were created (per label-approval policy).Issue #100 remains open pending owner confirmation or closure decision.