Two layers, one verdict
Your policy decides first. Then the strictest matching rule from the orgs this request asserted may tighten that decision, and only tighten it. Strictness is a rank — run, then ask, then block — and an org rule moves a verdict up it or leaves it alone. It can never turn yourask into a run.
When an org rule blocks, its note becomes the reason the person is shown.
The file
One file per org, inside the org’s own workspace:/orgs/acme/policy.json
format and rules are both required, and both objects are strict — an unknown
key is a parse failure, not a warning.
A rule is a match and an action.
Every
match field is optional and they are ANDed. An omitted field matches
anything, so {} matches every call.
This is not your deployment’s .vendo/policy.json with a field removed: an org
file has no directions, and its rules array is mandatory.
Why there is no “run”
Tighten-only is the whole design, and it is enforced three times.- The schema has no permissive action, so a console that sends
runis told at the moment the mistake is made rather than having its rule silently ignored on every call. - Within the org layer, the strictest matching rule wins.
- At the seam where the layer applies, the clamp is monotone: it raises the rank or does nothing.
Who may edit it
Every member of the org may read the file. Only a member yourmemberships seam
asserted with admin: true may write it.
That is a workspace rule, not a policy one, and nothing in the runtime writes the
file — today it is managed from the console.
Freshness and failure
The file is re-read per request behind a 30-second cache, so an admin’s edit binds within half a minute. The cache holds the file body, keyed on org id; the rules are re-parsed on each check. Failure is per-org and never widens anything:- A missing file means that org simply has no rules, and that answer is cached like any other.
- A file that cannot be read or does not parse drops that one org’s rules. Every other org in the request still binds. A read failure is deliberately not cached, so a blip cannot disarm an org for the whole window.
- Every drop is reported, never silently swallowed: a console warning naming the org
and the path, and an audit row with reason
org-policy-unavailable. A resolver that fails outright logsguard.org-policy-unavailable.
A keyed deployment with no local workspace can read no org policy at all. It says
so once, loudly, rather than pretending the layer is armed.
What a member sees
The same approval or refusal your own guard produces, because the org layer moves the verdict rather than replacing the experience. A call an org tightened toask parks for approval. A call an org blocked is
refused with the rule’s note, which is where an admin gets to say who to ask.
Where to go next
Orgs & memberships
The seam that decides whose rules load, and who counts as an admin.
admin: trueThe org workspace
The mount the file lives in, and the rest of the tree around it.
/orgs/<orgId>/**Handler options
Your deployment’s own guard — the floor an org builds on.
guard