Concepts
Policies
Rules that decide whether a credential access is allowed.
A policy is a rule that decides whether a credential access is allowed. Every credential-use request — app or agent, retrieve or proxy — is evaluated against the relevant policies before the token is injected; if the policy denies, the call raises PolicyViolationError and the provider is never reached. One exception: a request-quota denial (the window’s limit is spent) raises QuotaExceededError instead, which carries a retry-after — the seconds until the window resets. The SDKs never auto-retry it.
Policies sit between who can call (the principal on the grant) and what they’re allowed to call right now. The principal binding answers “is Alice’s grant?”; the policy answers “is now a valid time, from a valid place, within rate?”
Where a policy lives
Section titled “Where a policy lives”| Layer | Set by | Example |
|---|---|---|
| Organization policy | An organization administrator in the developer portal (dashboard-only — no CLI) | Require human-in-the-loop approval for sensitive operations in every application |
| Application policy | The operator in the developer portal or CLI | IP allowlist for every request in one application |
| Provider policy | The operator in the developer portal or CLI | Block sending through one provider |
| Managed secret policy | The operator in the developer portal or CLI | Allow only GET requests with one managed secret, including an internal API stored with the Custom template |
| Group policy | The operator in the developer portal or CLI | Allow contractors (an identity-provider group) only read requests, whichever connection or agent they use |
| Agent policy | The operator in the developer portal or CLI | Rate limit one managed agent |
| Connection policy | The operator or end user | Restrict one OAuth or managed-secret grant |
| Account policy | The end user in the Wallet, or the application in the developer portal or CLI; each edits only its own | The user requires human-in-the-loop approval across their accounts; the application blocks deletes for one user |
| Constrained-client policy | The SDK caller | Create a sub-client whose requests carry an additional non-stored rule |
Policies compose across the whole grant and delegation chain. A request that satisfies its connection policy but violates an application, group, agent, or account policy still fails.
Account and group policies follow the end user, not a connection: they apply to every request the user makes through the application, including through a connection their group holds, and to no other user. A group policy applies to the group’s active members, as the identity provider last reported them (see what groups can do).
The end user and the application each author account rules and each can change only its own. The user sees the application’s rules on their account in the Wallet, marked Set by the application (and the group, for a group rule), and cannot change or remove them; the application sees the user’s own limits in the developer portal and CLI and cannot change or remove those. Grant expiry (TTL) and scopes are separate access ceilings — set when the grant or key is created, not authored as policy rules — displayed alongside the effective policy chain.
A managed secret policy is the managed-secret counterpart of a provider policy. Provider policies apply to OAuth connections through that provider and never to managed-secret requests. A managed secret policy applies to every request that uses that secret, including requests through a connection an agent received by delegation, and to no OAuth request.
Where a rule applies
Section titled “Where a rule applies”A rule is created at one place, its home: the application, provider, managed secret, group, user, agent, or connection whose page (or CLI target) you created it from. It can then be attached to more places inside the same application, at any mix of those levels. One rule written once can restrict two agents, three users, or a provider and the agent that uses it, without authoring copies that drift apart. Every attachment is checked when it is added: the target must exist and belong to the same application.
A rule can also carry exceptions: agents, users, or groups the rule does not apply to, even though they fall under one of its attachments. For example, an application-wide read-only rule with an exception for a maintenance agent restricts every agent except that one; a group rule with an exception for the group’s lead restricts every other member; an application rule with an exception for a group restricts everyone outside it. An exception must be narrower than at least one of the rule’s attachments: a group under an application, provider, or managed secret; a user under one of those or a group; an agent under any of those or a user. An excepted user or group is exempt on every request that user or member makes. An agent exception follows delegation just as an attachment does: it also exempts every agent the excepted agent delegates to, even where a more specific attachment of the same rule matches, because a delegate never has more access than the agent it delegates from.
On each request, a rule applies when at least one of its attachments matches the request and none of its exceptions does. A rule is evaluated once per request, even when several of its attachments match. The home cannot be removed from a rule; to stop applying a rule at its home, delete the rule. Organization rules, account rules the end user authored in the Wallet, and rules managed by a settings page (such as a grant’s approval settings) apply only at their home and cannot be attached elsewhere.
The effective-rules view, Explain a request (the simulator) and the audit record of a denial all show which attachment matched, and the simulator shows the exception that excluded a rule when one did.
Attachments and exceptions change what a rule restricts, so they follow the same direction-of-effect permissions as editing a rule. Adding an attachment or removing an exception tightens access and needs the permission to create rules. Removing an attachment or adding an exception loosens access and needs the permission to delete rules, and the developer portal and CLI ask for confirmation first. Each change is version-checked and recorded in the audit log.
Revoking an attached agent, deleting an attached provider or managed secret, or the identity provider deleting an attached group removes that attachment (or exception) from the rule and records the removal in the audit log; the rule keeps applying everywhere else. A rule set on a deleted group moves to another place it is attached to, and is deleted only when it applies nowhere else. Deprovisioning a user removes nothing: the user’s attachments and exclusions stay, and apply again if the user is re-provisioned. Revoking an attached connection leaves its attachment in place: a revoked connection can never make another request, so the attachment has no effect, and it stays listed on the rule until you remove it. Deleting a rule’s home deletes the rule.
An exception for a group is an access its members keep until the identity provider reports they left. It can only be added when the provider revokes memberships in real time (Clerk, Okta or WorkOS with webhooks enabled, the same requirement as a group-bound grant); on any other setup it is refused with the reason. Disabling those webhooks is refused while such exceptions exist, and forcing the disable removes them.
What policies can express
Section titled “What policies can express”- Time-of-day windows — configurable day/time windows in a chosen timezone (e.g. business hours Mon–Fri, or an overnight maintenance window).
- IP allowlists — call only from listed IP addresses or CIDR ranges.
- Rate limits — cap calls per caller principal (agent when present, otherwise grant) per fixed window; over the limit, the call is denied with a retry-after until the window resets. This denial surfaces as
QuotaExceededError, notPolicyViolationError. - Attribute matches — deny requests matching metadata conditions: the HTTP method, the provider, the acting agent, the source IP, or the classified operation/family (“deny everything in the
paymentfamily”). - Method/endpoint restrictions — allowlist the HTTP methods and provider API paths traffic may use (“GET only”, “
/repos/**only”); enforced on proxied calls, so a restricted connection refuses raw-token retrieval. - Approval requirements — route to a human-in-the-loop decision before executing, including multi-party (N-of-N) approval where distinct approver gates from applicable rules must each be approved, and parameter-conditional approvals (“only payments over $1,000 need sign-off”).
- Operation-level rules — bind a specific provider operation or a semantic family of operations (“everything that sends”, “everything that moves money”) from Alter’s reviewed operation catalog: “this agent may read Gmail but never send.”
- Parameter-level rules — conditions over what a request actually carries, canonicalized across provider formats: “may only email addresses at
@acme.com”, “may not move more than $1,000.” A request the policy engine cannot fully classify is refused rather than guessed at. - Redaction — remove named fields from a matching request before it reaches the provider (for example, the subject line of an outbound email, which is then sent without a subject). Nothing is written in place of a removed field, and the call is refused if the removal cannot be provably applied.
- Step-up authentication — require the acting end user to have signed in recently (“within the last 5 minutes”) for sensitive operations; a stale or unprovable session is refused with a clear re-authentication signal.
The last four are variants of one rule shape: a content-match rule binds a match — specific operations or semantic families from the cataloged operation catalog, optionally narrowed by conditions over the request’s canonicalized parameters — to one of three effects: deny (refuse the call), redact (remove named fields before the call is executed — nothing is substituted — refusing if the removal cannot be provably applied), or step_up (require a sufficiently recent end-user sign-in). The SDKs expose typed builders for it (content_match_rule in Python, contentMatchRule in TypeScript), which validate the rule locally — effect-specific requirements included — before it is ever sent.
The developer portal and Wallet use the same structured editor and policy viewer. Owned rules show the complete definition: target, effect, operations, every parameter condition, status, source, and metadata. Inherited Wallet controls use the same viewer with disclosure-safe summaries that omit developer-only values. The CLI renders the same normalized explanation with alter policy rules get --output table; JSON remains the default for automation.
with_constraints (Python) and withConstraints (TypeScript) return constrained sub-clients. Every request made through that sub-client carries the additional rule; the original client remains unconstrained. Retain the original client for calls that should not carry the rule.
Fail-closed
Section titled “Fail-closed”If a policy cannot be evaluated (the policy engine is unreachable, the inputs are malformed, the policy version drifted), the request is denied. No call is made; no token leaves the vault. The error surfaces as PolicyViolationError with the failure reason on policy_error.
This is the opposite of fail-open systems where a missing policy is treated as “no rule, allow.” Alter treats a missing policy evaluator as “no decision, deny.”
Every policy decision (allow, deny, or error — error meaning the policy gate itself failed to evaluate and the request was denied fail-closed) emits an audit event with the deciding policy metadata and outcome. Projected parameter values are not logged. Denied calls never reach the provider and normally appear in the audit trail as first-class compliance evidence. If audit storage itself fails, the request result is preserved while critical gap telemetry and a fallback audit attempt make the missing record observable; see Security architecture.
What’s next
Section titled “What’s next”- Set policies — a step-by-step walkthrough for authoring each rule type from the dashboard, the CLI, and the SDK.
- Audit logs — where policy decisions are recorded.
- Add human-in-the-loop approvals — policy-driven approval flow.
- Security architecture — the policy engine in the larger picture.