Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions realm-policy/realm-policy.gts
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,16 @@ export class OperationGrant extends FieldDef {
@field where = contains(PolicyPredicateField);
// Whether the grant also admits a caller who isn't signed in. Off, it
// admits only signed-in callers, so a grant written before anonymous
// callers could reach a policy never starts admitting them. Only a grant on
// a base operation under its own name (`read`, `update`, …) may set it, not
// one on a custom operation or a named query. The realm doesn't evaluate a
// `where` that reads `actor()` for such a caller, so a grant whose `where`
// does never admits one: an anonymous grant is scoped by what the target
// holds. How hard anonymous callers may use the realm, and which addresses
// it refuses, are the governed realm's own settings, not the policy's.
// callers could reach a policy never starts admitting them. A grant on a
// base operation other than `explain` or `validate` may set it, and so may
// one on an operation a card declares on such a base. A grant on a named
// query may not: setting it there leaves the whole grant out, for
// signed-in callers too. Such a caller has no actor, so a grant whose
// `where` reads `actor()`, or whose operation does, never admits one,
// though it still applies to signed-in callers: an anonymous grant is
// scoped by what the target holds. How hard anonymous callers may use the
// realm, and which addresses it refuses, are the governed realm's own
// settings, not the policy's.
@field anonymous = contains(BooleanField);
// For an anonymous grant on a write: the key, exactly as written, in the
// governed realm's `realm.json` settings, whose value is the user the write
Expand Down Expand Up @@ -389,8 +392,9 @@ export class PolicyRule extends FieldDef {
}

// What each reason an explanation gives means, in the words a policy author
// reads it in.
const REASONS: Record<PolicyExplanation['reason'], string> = {
// reads it in. `reads-actor` is named here as well as through the explanation
// type, so the map covers it whichever platform version this realm runs on.
const REASONS: Record<PolicyExplanation['reason'] | 'reads-actor', string> = {
acl: "The realm's own permissions already allow this, so the policy isn't needed.",
granted: 'A grant in this policy allows it.',
'no-grant': "No rule for this card's type grants this operation.",
Expand All @@ -408,6 +412,8 @@ const REASONS: Record<PolicyExplanation['reason'], string> = {
'not-resolved': "This card doesn't have this operation.",
'actor-required':
"Someone who isn't signed in is turned away before the policy is checked.",
'reads-actor':
"This operation depends on who is asking, and someone who isn't signed in can't be identified, so a grant that opens it to them doesn't apply.",
'policy-unloadable': "The realm's policy couldn't be loaded.",
};

Expand Down Expand Up @@ -1400,6 +1406,9 @@ class ExplainPanel extends GlimmerComponent<ExplainPanelSignature> {
data-test-explain-actor
/>
</FieldContainer>
<p class='hint' data-test-explain-actor-hint>
Leave this empty to check what someone who isn't signed in can do.
</p>
{{#if this.isCard}}
<FieldContainer
@label='Card (URL)'
Expand Down
Loading