Skip to content

Access Control (Petitio)

Per-agent access control (Petitio)

Petitio is Portunus's policy layer. It sits between every resolution request and the vault backend, enforcing two kinds of gates: a lifecycle/approval gate (always active) and a role-based access control (RBAC) system (configurable, default off).


Default behavior: fully open

A reference with no configured policy is always resolvable by any caller. This is the "permissive-if-unconfigured" posture: enforcement only ever narrows access for a scope that has at least one policy record. A fresh vault has no records — every resolve succeeds.


Role-based access control

RBAC policies persist in PORTUNUS_HOME/roles.json (0600). Each policy record covers one scope dimension and one principal.

Scope dimensions

Policies match references by one of four dimensions:

Scope type Matches
org References whose org field equals the scope value
project References whose project field equals the scope value
env References whose env field equals the scope value
repo References whose repo field equals the scope value

Setting a policy

portunus roles set \
  --scope-type project \
  --scope-value my-project \
  --role dev \
  --actions read,test \
  --principal my-agent-name

--principal names which agent or identity the policy applies to. Omit it (or pass *) to apply the record to everyone. Two records with the same scope and role but different principals are stored independently.

--actions is a comma-separated list of free-text strings; Portunus records them as-is and does not interpret them at enforcement time — they exist for documentation and for a future policy engine to act on.

Viewing policies

# Show all configured policies
portunus roles show

# Filter by dimension
portunus roles show --scope-type project --scope-value my-project

Deleting a policy

portunus roles delete \
  --scope-type project \
  --scope-value my-project \
  --role dev \
  --principal my-agent-name

Activating enforcement

By default, policy evaluation runs in audit-only mode: every resolve logs a would-allow or would-deny result to the audit chain but never raises an error. This lets you review the audit log before committing to enforcement.

Turn enforcement on or off:

portunus roles enforce on
portunus roles enforce off
portunus roles enforce status   # check current state

When enforcement is on, a would-deny decision raises NotAuthorized and aborts the resolve. The permissive-if-unconfigured rule still applies: a scope with zero policy records always allows, regardless of the enforcement setting.


Concrete example: multi-agent system

Say you have two agents: agent-prod (handles production deploys) and agent-dev (general development). You want agent-prod to have access to production references and agent-dev to be blocked from them.

# Grant agent-prod access to the production project
portunus roles set \
  --scope-type env \
  --scope-value prod \
  --role deployer \
  --actions read \
  --principal agent-prod

# Confirm audit-only mode shows the right behavior before enabling enforcement
portunus audit

# Enable enforcement
portunus roles enforce on

After this, agent-dev attempting to resolve a prod reference will log would-deny and — with enforcement on — receive a NotAuthorized error. agent-prod resolves normally.


Approval gate

Separate from RBAC, individual references can require explicit human approval before any resolve is allowed.

# Require approval on a reference
portunus gate my-ref

# Grant a time-boxed approval (measured in audit-clock ticks, default 3)
portunus approve my-ref --ttl 5

# Remove the gate
portunus gate my-ref --off

The approval is scoped to the reference name only — not to the requesting identity. Any caller can resolve an approved reference until the approval expires. This is a known gap: future work will scope approvals to a specific principal.


Grant

portunus grant records an explicit, audited widening of access for a named member. This writes an audit entry regardless of whether GCP IAM changes are actually applied:

portunus grant my-ref some-member@example.com