Skip to content

Commit efe9a84

Browse files
committed
fix(psp-1):
- Added a Rationale explain why syntactic attenuation is defined mechanically. - Added a Rationale for ephemeral presentations - Updated the CDDL grammar comment for `Literal` to clarify that `op` is an operator string. - Lifted the prohibited/non-canonical forms
1 parent 6fe9158 commit efe9a84

File tree

1 file changed

+72
-30
lines changed

1 file changed

+72
-30
lines changed

docs/reference/specifications/psp-1.mdx

Lines changed: 72 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -738,23 +738,32 @@ normalization rules (PCF).
738738
"Pairs#CID") MUST be encoded deterministically and consistently wherever they
739739
appear.
740740

741-
#### Prohibited/non-canonical forms
741+
### 7.4 Prohibited and Non-Canonical Forms
742742

743-
- Floating-point numbers MUST NOT appear in Programs.
744-
- Indefinite-length encodings and non-normalized strings MUST NOT appear in
745-
canonical bytes (see PSP-3 for encoding constraints).
746-
- Any literal or term introducing non-determinism or network I/O MUST NOT be
747-
part of a Program.
743+
Certain forms are incompatible with deterministic canonicalization and MUST NOT
744+
appear in a CPL/0 Program or its canonical representation:
748745

749-
### 7.4 Deterministic encoding and identity
746+
- Floating-point numbers: Programs MUST NOT contain floating-point values. CPL/0
747+
supports only arbitrary-precision integers.
748+
- Indefinite-length encodings and non-normalized strings: All strings MUST be
749+
NFC-normalized and encoded with definite lengths. Indefinite-length encodings
750+
and non-normalized strings MUST NOT appear in the canonical bytes (see PSP-3
751+
for encoding constraints).
752+
- Non-determinism or network I/O: Any literal or term that would introduce
753+
non-determinism (e.g., entropy, randomness) or perform network/external I/O
754+
MUST NOT be part of a Program. Builtins are pure and deterministic by
755+
construction; user-defined or environment-sourced non-deterministic operations
756+
are out of scope for CPL/0.
757+
758+
### 7.5 Deterministic encoding and identity
750759

751760
- `programBytes` = ENCODE(PCF(Program)) as specified by PSP-3.
752761
- `programId` = multihash(`programBytes`) as specified by PSP-3.
753762
- A Grant carrying `programBytes` and `programId` MUST be rejected if
754763
recomputation does not match.
755764
- ENCODE is defined in PSP-3; PCF is defined here in PSP-1.
756765

757-
### 7.5 Failure handling
766+
### 7.6 Failure handling
758767

759768
- Canonicalization MUST fail, and verification MUST deny, if a Program contains
760769
an unknown operator, ill-typed arguments under a builtin's signature,
@@ -763,14 +772,14 @@ normalization rules (PCF).
763772
deny during evaluation. If such references prevent deterministic term
764773
encodings, identity derivation MUST fail.
765774

766-
### 7.6 Stability and tests
775+
### 7.7 Stability and tests
767776

768777
- Canonicalization is part of the trusted computing base. Implementations SHOULD
769778
cross-test that semantically identical Programs (after literal reordering,
770779
duplicate removal, and string normalization) yield identical `programBytes`
771780
and `programId` across platforms and versions.
772781

773-
### 7.7 Informative guidance
782+
### 7.8 Informative guidance
774783

775784
Keep operator identifiers stable and registry-pinned to avoid PCF instability
776785
from renaming. When referencing Declarations by content address (e.g.,
@@ -971,6 +980,19 @@ small and referential in PSP-1 core.
971980
- Runtime facts: Conveys ctx and timing (iat/exp) the CEP uses to evaluate the
972981
Program's literals (e.g., ctxEq, ttlOk, withinTime).
973982

983+
#### 10.2 Rationale
984+
985+
Presentations are intentionally ephemeral. Unlike Grants, which are durable and
986+
recorded on sigchains, a Presentation conveys proof-of-possession only for the
987+
duration of a single live session. Short-lived tokens dramatically reduce the
988+
window in which an attacker could replay or steal a capability. They also allow
989+
time-bounded constraints (e.g., `ttlOk`, `withinTime`) and context-dependent
990+
predicates (`channelBinding`, `ctxEq`) to be enforced on each invocation without
991+
recording sensitive per-use context on a public ledger. Persisting Presentations
992+
or allowing them to be reused indefinitely would undermine these protections,
993+
enable unauthorized redistribution, and blur the distinction between durable
994+
Grants and transient proof-of-use.
995+
974996
### 10.2 Structure (Informative Projection)
975997

976998
Note: The names below are non-normative conceptual labels used by PSP-1. The
@@ -1120,6 +1142,23 @@ enforced by the CEP with no network I/O during Program evaluation.
11201142
depth/fan-out caps or strict attenuation requirements). PSP-1 permits equality
11211143
by default.
11221144

1145+
#### 11.2 Rationale
1146+
1147+
Syntactic attenuation is not an arbitrary design choice; it is a deliberate
1148+
restriction that makes delegation mechanically checkable and removes subjective
1149+
interpretations of what "controls authority". By requiring that child Grants
1150+
retain all parent Checks, may drop Queries to narrow ORs, and only tighten
1151+
literal constants and Declaration sets, the CEP can verify attenuation purely
1152+
through structural subset relations. This mirrors the checks-only fragment of
1153+
Biscuit tokens and ensures that independent implementations will make identical
1154+
decisions when verifying a delegation chain. Without syntactic rules, issuers
1155+
could embed logic that ambiguously broadens or narrows authority, making it
1156+
difficult or impossible for CEPs to decide whether a child Grant has overstepped
1157+
the parent. The syntactic approach also dovetails with PCF canonicalization:
1158+
reordering of checks or literals does not affect identity, and monotonicity is
1159+
explicit in the Program structure. See the 14. Security Considerations for
1160+
additional discussion of the risks mitigated by syntactic attenuation.
1161+
11231162
### 11.2 Chain Structure and Custody
11241163

11251164
- Hop custody
@@ -1415,8 +1454,8 @@ Preconditions (TAP-governed, outside evaluation)
14151454
- presenterIs (if used)
14161455
- Enforce type checks; ill-typed literals -> deny.
14171456
- Enforce resource bounds (CPU/steps/memory). Exceeding limits MUST result in
1418-
deny. (Deployments SHOULD use an appropriate reason code from the PSP-2
1419-
registry to indicate a resource limit or deadline breach.)
1457+
deny. (The enforcing CEP SHOULD use an appropriate reason code from the
1458+
PSP-2 registry to indicate a resource limit or deadline breach.)
14201459
- Unknown builtin, unknown lattice, or unknown scheme comparator required by
14211460
the Program -> deny.
14221461
- Context superset: ctx MUST include all required ctxEq(k, v) literals with
@@ -1425,17 +1464,20 @@ Preconditions (TAP-governed, outside evaluation)
14251464
- On success:
14261465
- Allow enforcement per placement/mode (mediate/derive/reveal are defined
14271466
outside PSP-1).
1428-
- Deployments MAY emit an Access PoAR to record the decision. When a PoAR
1429-
is produced, it MUST conform to PSP-2. PoARs MUST include `programId`,
1430-
declaration CIDs, pins (including `schemesSnapshotId`), a minimal
1431-
evaluation trace (which check/query passed), revocation/freshness
1467+
- The enforcing CEP MUST record a decision event for the authorization
1468+
outcome. If the CEP implements PSP-2 receipts, the enforcing CEP MUST
1469+
emit an Access PoAR to record the decision. PoARs MUST include
1470+
`programId`, declaration CIDs, pins (including `schemesSnapshotId`), a
1471+
minimal evaluation trace (which check/query passed), revocation/freshness
14321472
decision context, comparator fingerprints, and the enforcer measurement
14331473
(`adapterRef`).
14341474
- On failure:
1435-
- Deployments MAY emit a DenyReceipt. When a DenyReceipt is emitted, it
1436-
MUST conform to PSP-2 and include a reason code from the PSP-2 registry.
1437-
As with PoARs, DenyReceipts SHOULD avoid disclosing sensitive detail and
1438-
SHOULD record enough context for auditors to reconstruct the decision.
1475+
- The enforcing CEP MUST record a decision event for the authorization
1476+
outcome. If the CEP implemnts PSP-2 receipts, the enforcing CEP MUST emit
1477+
a DenyReceipt. DenyReceitps MUST include a reason code from the PSP-2
1478+
registry. As with PoARs, DenyReceipts SHOULD avoid disclosing sensitive
1479+
detail and SHOULD record enough context for auditors to reconstruct the
1480+
decision.
14391481

14401482
### 13.3 Execution Constraints
14411483

@@ -1447,11 +1489,11 @@ Preconditions (TAP-governed, outside evaluation)
14471489
- TAP governs clock source and skew tolerance; the CEP MUST apply TAP's
14481490
discipline to all time comparisons. If time discipline cannot be satisfied
14491491
(e.g., clock indeterminate), the CEP MUST deny.
1450-
- Deadlines and budgets
1492+
- Deadlines and budgets
14511493
- The CEP MUST enforce bounded evaluation (CPU/steps/memory). If TAP sets a
14521494
per-request deadline, the CEP MUST abort and deny when the deadline is
1453-
reached. Deployments SHOULD log an appropriate reason code as defined by the
1454-
PSP-2 registry.
1495+
reached. The enforcing CEP SHOULD log an appropriate reason code as defined
1496+
by the PSP-2 registry.
14551497
- Closed-world inputs
14561498
- All required inputs (leaf Grant, parent Grants, revocation state) MUST be
14571499
locally available at the start of enforcement; otherwise the CEP MUST deny.
@@ -1543,8 +1585,8 @@ across delegation, and (d) TAP-governed acceptance and deployment hygiene.
15431585

15441586
- Resource budgets
15451587
- CEPs MUST enforce CPU/steps/memory limits for Program evaluation. Exceeding
1546-
limits MUST result in deny. Deployments SHOULD log an appropriate reason code
1547-
from the PSP-2 registry to indicate a resource or deadline violation.
1588+
limits MUST result in deny. The enforcing CEP SHOULD log an appropriate reason
1589+
code from the PSP-2 registry to indicate a resource or deadline violation.
15481590
- Input bounds
15491591
- Programs and Declarations MUST remain finite. CEPs SHOULD bound sizes of
15501592
`programBytes`, declaration tables, and `ctx` to mitigate memory/CPU
@@ -2001,7 +2043,7 @@ Query = {
20012043
20022044
; Literal = Builtin(op, args...)
20032045
Literal = {
2004-
op: tstr, ; operator id (e.g., "withinTime", "inPairSet")
2046+
op: tstr, ; operator string (op) (e.g., "withinTime", "inPairSet")
20052047
args: [* Term]
20062048
}
20072049
@@ -2037,11 +2079,11 @@ Conformance notes:
20372079

20382080
This appendix enumerates the builtin operators assumed by PSP-1 and the
20392081
tightening rules used for syntactic attenuation. The authoritative registry of
2040-
operators (opIds, types, and semantics) is modeled in PSP-4; Grants pin the
2041-
exact set via `builtinsId`.
2082+
operators (`op` strings, types, and semantics) is modeled in PSP4; Grants pin
2083+
the exact set via `builtinsId`.
20422084

20432085
**Builtin operations (what & how).** CPL/0 Programs are conjunctions of builtin
2044-
**literals**. Each literal is an `opId` plus arguments (e.g.,
2086+
**literals**. Each literal is an `op` string plus arguments (e.g.,
20452087
`withinTime(now, nbf, exp)` or `inPairSet(action, resource, "cid")`). Builtins
20462088
are **pure, deterministic, and resource-bounded**; they perform no network I/O
20472089
and return Booleans. A Grant's `builtinsId` pins a content-addressed snapshot of
@@ -2050,7 +2092,7 @@ invocations.
20502092

20512093
**Builtin operations summary**
20522094

2053-
| opId | type signature | returns | semantics (informative shorthand) | tightening (child vs parent) | fail-closed |
2095+
| op | type signature | returns | semantics (informative shorthand) | tightening (child vs parent) | fail-closed |
20542096
| --------------- | ------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- |
20552097
| `withinTime` | `(now:Int, nbf:Int, exp:Int)` | Bool | `nbf <= now < exp` | `[nbf_child >= nbf_parent $\land$ exp_child <= exp_parent]` | ill-typed => deny; else boolean result |
20562098
| `ttlOk` | `(iat:Int, now:Int, ttlMax:Int)` | Bool | `now < iat + ttlMax` | `ttlMax_child <= ttlMax_parent` | ill-typed => deny; else boolean result |

0 commit comments

Comments
 (0)