Skip to content

Latest commit

 

History

History
208 lines (133 loc) · 8.45 KB

File metadata and controls

208 lines (133 loc) · 8.45 KB
title Explain
description Explain protocol schemas

{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}

[ADR-0090 D6] Access-explanation contract — `explain(principal, object,

operation)` as a first-class API.

The explain engine (@objectstack/plugin-security) walks the SAME code

paths as the enforcement middleware — the same permission-set resolution,

the same evaluator, the same RLS compiler — and reports what each layer of

the evaluation pipeline contributed to the final decision. "Explained by

construction": the report can never drift from enforcement because it IS

enforcement, minus the throw.

Layer order mirrors the runtime pipeline:

tenant_isolation → principal → required_permissions → object_crud → fls →

owd_baseline → depth → sharing → vama_bypass → rls.

[C2 / ADR-0095] Record-grained explanation. The contract carries an optional

recordId on the request and, when present, a per-layer record attribution

plus a top-level record verdict on the response — so the sharing / rls / owd

layers can report the ROW-LEVEL story for one concrete record (which share

admitted it, which filter excluded it, whether the effective row filter

matches). Object-level requests (no recordId) stay byte-compatible.

[ADR-0095 D1/D2] The contract also reserves the kernel-chain vocabulary the

β engine + UI will fill: the always-first tenant wall as tenant_isolation

(Layer 0), a per-layer kernelTier marking Layer 0 vs. business RLS

(Layer 1), and the monotonic posture ladder

(PLATFORM_ADMIN > TENANT_ADMIN > MEMBER > EXTERNAL) on the resolved principal.

**Source:** `packages/spec/src/security/explain.zod.ts`

TypeScript Usage

import { AccessMatrix, AccessMatrixEntry, AuthzPosture, ExplainDecision, ExplainLayer, ExplainMatchedRule, ExplainOperation, ExplainRecordAttribution, ExplainRequest } from '@objectstack/spec/security';
import type { AccessMatrix, AccessMatrixEntry, AuthzPosture, ExplainDecision, ExplainLayer, ExplainMatchedRule, ExplainOperation, ExplainRecordAttribution, ExplainRequest } from '@objectstack/spec/security';

// Validate data
const result = AccessMatrix.parse(data);

AccessMatrix

Properties

Property Type Required Description
version '1'
entries { permissionSet: string; object: string; create: boolean; read: boolean; … }[]

AccessMatrixEntry

Properties

Property Type Required Description
permissionSet string
object string
create boolean
read boolean
edit boolean
delete boolean
viewAllRecords boolean
modifyAllRecords boolean
readScope string optional
writeScope string optional
sharingModel string optional

AuthzPosture

ADR-0095 D2 posture rung — PLATFORM_ADMIN crosses the tenant wall where object posture permits; TENANT_ADMIN sees all rows in the org; MEMBER gets business RLS; EXTERNAL sees only explicitly shared rows.

Allowed Values

  • PLATFORM_ADMIN
  • TENANT_ADMIN
  • MEMBER
  • EXTERNAL

ExplainDecision

Properties

Property Type Required Description
allowed boolean
object string
operation Enum<'read' | 'create' | 'update' | 'delete' | 'transfer' | 'restore' | 'purge' | 'export'>
principal { userId: string | null; positions: string[]; permissionSets: string[]; principalKind?: Enum<'human' | 'agent' | 'service' | 'guest' | 'system'>; … }
layers { layer: Enum<'tenant_isolation' | 'principal' | 'required_permissions' | 'object_crud' | 'fls' | 'owd_baseline' | 'depth' | 'sharing' | 'vama_bypass' | 'rls'>; kernelTier?: Enum<'layer_0_tenant' | 'layer_1_business'>; verdict: Enum<'grants' | 'denies' | 'narrows' | 'widens' | 'neutral' | 'not_applicable'>; detail: string; … }[]
readFilter any optional
record { recordId: string; visible: boolean; decidedBy?: Enum<'tenant_isolation' | 'principal' | 'required_permissions' | 'object_crud' | 'fls' | 'owd_baseline' | 'depth' | 'sharing' | 'vama_bypass' | 'rls'> } optional Row-level verdict for the specific record; set only for record-grained requests.

ExplainLayer

Properties

Property Type Required Description
layer Enum<'tenant_isolation' | 'principal' | 'required_permissions' | 'object_crud' | 'fls' | 'owd_baseline' | 'depth' | 'sharing' | 'vama_bypass' | 'rls'>
kernelTier Enum<'layer_0_tenant' | 'layer_1_business'> optional ADR-0095 kernel layer: layer_0_tenant = the always-first org wall; layer_1_business = business RLS/sharing/ownership.
verdict Enum<'grants' | 'denies' | 'narrows' | 'widens' | 'neutral' | 'not_applicable'>
detail string
contributors { kind: Enum<'permission_set' | 'position' | 'system'>; name: string; via?: string; state?: Enum<'active' | 'expired'> }[]
record { outcome: Enum<'admitted' | 'excluded' | 'not_evaluated'>; rowFilter?: any; matchesRecord?: boolean; rules: { kind: Enum<'tenant_filter' | 'owd_baseline' | 'ownership' | 'record_share' | 'sharing_rule' | 'team' | 'territory' | 'rls_policy'>; name: string; grants?: Enum<'read' | 'edit' | 'full'>; via?: string; … }[]; … } optional Row-level determination for the specific record under explanation; set only for record-grained requests.

ExplainMatchedRule

Properties

Property Type Required Description
kind Enum<'tenant_filter' | 'owd_baseline' | 'ownership' | 'record_share' | 'sharing_rule' | 'team' | 'territory' | 'rls_policy'> The row-visibility source kind evaluated for this record at this layer.
name string Stable identifier of the concrete rule, share, or policy that was evaluated.
grants Enum<'read' | 'edit' | 'full'> optional Access level a sharing source grants on the record (mirrors SharingLevel).
via string optional How the rule reached the principal — recipient group/position, ownership, or the matching criteria.
predicate any optional The row predicate this rule contributed, when it is filter-shaped (null = unrestricted).
effect Enum<'admits' | 'excludes' | 'neutral'> The rule's effect on THIS record: admits, excludes, or neutral.

ExplainOperation

Allowed Values

  • read
  • create
  • update
  • delete
  • transfer
  • restore
  • purge
  • export

ExplainRecordAttribution

Properties

Property Type Required Description
outcome Enum<'admitted' | 'excluded' | 'not_evaluated'> This layer's row-level outcome for the record: admitted, excluded, or not_evaluated (skipped/not row-scoped).
rowFilter any optional The effective row predicate this layer contributed for the record set (null = unrestricted, deny_all = zero rows).
matchesRecord boolean optional Whether the specific record satisfies rowFilter — the judgement behind outcome.
rules { kind: Enum<'tenant_filter' | 'owd_baseline' | 'ownership' | 'record_share' | 'sharing_rule' | 'team' | 'territory' | 'rls_policy'>; name: string; grants?: Enum<'read' | 'edit' | 'full'>; via?: string; … }[] Concrete rules, shares, or policies this layer evaluated against the record, in evaluation order.
detail string optional Human-readable, record-specific explanation of this layer's outcome.

ExplainRequest

Properties

Property Type Required Description
object string
operation Enum<'read' | 'create' | 'update' | 'delete' | 'transfer' | 'restore' | 'purge' | 'export'>
recordId string optional Optional id of one concrete record to explain at row granularity; omitted = object-level (pre-C2) request.
userId string optional