@@ -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
775784Keep operator identifiers stable and registry-pinned to avoid PCF instability
776785from 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
976998Note: 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...)
20032045Literal = {
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
20382080This appendix enumerates the builtin operators assumed by PSP-1 and the
20392081tightening 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 PSP‑ 4; 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
20462088are ** pure, deterministic, and resource-bounded** ; they perform no network I/O
20472089and 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