Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This file records material changes to the Context Layer working draft and its pu

## Unreleased

- Add the 2026-09 protocol proposal as a working draft: closed 0.2 Lite remains authoritative; `context-layer/0.3-draft` CL-Pass companions and T01–T10 vectors sit beside it.
- Confirm the dual-license boundary and contribution terms before publishing the first proof-of-work prerelease.
- Populate the canonical protocol-only GitHub repository from the reviewed release commit.
- Consolidate specification, reference, schema, and fixture artifacts under the explicit `protocol/` boundary; keep website and deployment source outside this repository.
Expand Down
4 changes: 4 additions & 0 deletions LICENSING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ Website application, hosting, and deployment source are intentionally outside th

If a file combines executable software with embedded explanatory prose and is not explicitly listed in the documentation section, Apache-2.0 applies to the whole file. Third-party dependencies, quoted standards text, linked external material, trademarks, and generated dependency notices remain governed by their own terms.

## Protocol proposal (2026-09)

The 2026-09 protocol proposal and `protocol/companions/0.3-draft` companion materials are part of this repository. Schemas, examples, and other executable companion artifacts use Apache-2.0. Proposal prose, companion specification pages, and `test-vectors/cl-pass/VECTORS.md` use CC BY 4.0. This note does not relicense the existing v0.2 product or replace `LICENSE` / `LICENSE-DOCS`.

No license grants trademark rights or implies endorsement, protocol adoption, production readiness, security certification, or warranty.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This is the canonical public repository for both the protocol and its published
- [Experimental local core](packages/local-core/)
- [Threat model](docs/context-layer-threat-model.md)
- [Executable v0.2 vectors](test-vectors/v0.2/)
- [2026-09 protocol proposal (0.2 Lite + 0.3 CL-Pass)](docs/proposals/2026-09-protocol-proposal.md)

## Protocol flow

Expand Down Expand Up @@ -107,6 +108,16 @@ npx vercel dev site

The repository test suite verifies that all published routes and their required assets remain present. Changes to public copy or design should be made here first so the repository and live documentation cannot silently diverge.

## Protocol proposal (2026-09)

The 2026-09 proposal keeps `CL-Core-Lite` closed and adds a reviewable `context-layer/0.3-draft` companion pack (CL-Pass) beside it. This does not open the five Lite schemas or mint a live issuer.

| Path | Purpose |
| --- | --- |
| [docs/proposals/2026-09-protocol-proposal.md](docs/proposals/2026-09-protocol-proposal.md) | Technical write-up (working draft) |
| [protocol/companions/0.3-draft/](protocol/companions/0.3-draft/) | Companion objects, closed schemas, examples |
| [test-vectors/cl-pass/VECTORS.md](test-vectors/cl-pass/VECTORS.md) | Required T01–T10 oracles (schema-valid JSON is not a pass) |

## Security and licensing

Report vulnerabilities through [GitHub private vulnerability reporting](https://github.com/sierracatalina/context-layer/security/advisories/new); do not post exploit details in a public issue.
Expand Down
146 changes: 146 additions & 0 deletions docs/proposals/2026-09-protocol-proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Context Layer — 2026-09 protocol proposal

| Field | Value |
| --- | --- |
| Status | Working draft — not an adopted standard |
| Date | 2026-09-13 |
| Closed Lite | `context-layer/0.2-draft` CL-Core-Lite |
| Companion profile | `context-layer/0.3-draft` CL-Pass |
| Repo | https://github.com/sierracatalina/context-layer |
| License | Existing repository boundary (Apache-2.0 software / CC BY 4.0 prose). This proposal does not relicense v0.2. |

This is the 2026-09 proposal write-up. It states what is already closed, what the 0.3 companions add beside Lite, and what this proposal does not do.

## What Context Layer is

Context Layer is a protocol for moving the minimum useful context across applications, models, and agents while keeping authority with the user. The vault is user-owned. Isolation is purpose-bound: a consumer receives an approved scoped bundle, not an unrestricted vault query interface.

Every disclosing exchange begins with a declared purpose, passes through policy, produces a recipient-bound scoped bundle, and leaves a minimized receipt. New memory enters only as a proposal. Authentication of a principal is not authorization to read the vault.

The published v0.2 product (schemas, reference runtime, local-core proof, public dossier) remains the closed Lite line. This proposal does not open those objects.

## Closed 0.2 Lite

The five CL-Core-Lite objects stay closed (`additionalProperties: false`). Implementations MUST reject unknown top-level fields. Version `0.2-draft` does not define portable `extensions` or `required_extensions` members.

| Object | Role |
| --- | --- |
| `context_request` | Purpose-bound ask: requester, recipient, `purpose_code`, `{ predicate }` selectors, actions, retention, receipt requirement, expiry |
| `policy_decision` | Four-state outcome: `allow`, `allow_with_reductions`, `deny`, `needs_approval` |
| `scoped_context_bundle` | Recipient-bound, single-use, expiring packet of approved claims only |
| `memory_update_proposal` | Proposal-only writeback; commit is not a standing read grant |
| `receipt` | Payload-minimized evidence (`payload_included` is `false`) |

Authoritative schemas: [`protocol/schemas/`](../../protocol/schemas/). Synthetic fixtures: [`protocol/fixtures/`](../../protocol/fixtures/). Executable v0.2 vectors: [`test-vectors/v0.2/`](../../test-vectors/v0.2/).

### Flow

```text
context_request
-> policy_decision
-> scoped_context_bundle (only on allow / allow_with_reductions)
-> capability-bound action
-> receipt
-> memory_update_proposal (optional; review then commit)
```

`needs_approval` is a successful protocol outcome. It is not a transport failure and it is not a read.

### Why Lite stays closed

Lite is the interoperable experiment surface. Opening it to carry identity, pairing, pass, approval-handle, lifecycle, or annotation fields would:

- silently treat unknown members as authorized extensions;
- let a schema-valid identity object masquerade as a grant;
- mix pairing and pass into the request/decision/bundle contract;
- make T01–T10 oracles untestable against a stable baseline.

0.3 companions are therefore **not Lite patches**. They use `spec_version: context-layer/0.3-draft` and `additionalProperties: false` on their own objects. Reason codes such as `IDENTITY_ONLY`, `PAIRING_REQUIRED`, `PURPOSE_NOT_ON_PASS`, `CATEGORY_NOT_ON_PASS`, and `PASS_REVOKED` travel on the existing `policy_decision.reason_codes` array. They are not new Lite fields.

## 0.3 / CL-Pass companions

Companion pack: [`protocol/companions/0.3-draft/`](../../protocol/companions/0.3-draft/).

| Object | Role |
| --- | --- |
| `identity_assertion` | Authenticates a principal. `context_grant` MUST be `false`. |
| `client_pairing` | Admits an exact `client_instance` only. Pairing is not a pass. |
| `context_pass` | Grants `memory_category` values and allowed purpose codes. Necessary, not sufficient. |
| `approval_handle` | Returned on `needs_approval`. MUST NOT carry claim text or vault payloads. |
| `lifecycle_event` | Content-free lifecycle beside receipts. `payload_included` MUST be `false`. |
| `claim_annotation` | Rides beside claims until a 0.3 core revision. Evidence labels MUST NOT be upgraded. |
| `memory_category` | Closed enum: `preference` \| `fact` \| `project` \| `instruction` |

Companion schemas, examples, README, spec, and T01–T10 vectors live under [`protocol/companions/0.3-draft/`](../../protocol/companions/0.3-draft/) and [`test-vectors/cl-pass/VECTORS.md`](../../test-vectors/cl-pass/VECTORS.md). Do not invent types.

### Invariants (normative for CL-Pass)

1. **Identity ≠ grant.** `identity_assertion.context_grant` MUST be `false`. Authenticating a principal MUST NOT disclose vault claims.
2. **Identity-only is not authorized disclosure.** A consumer holding only an identity assertion MUST NOT be treated as authorized to submit a disclosing `context_request` and MUST NOT be issued a `scoped_context_bundle`.
3. **Pairing ≠ pass.** `client_pairing` admits an exact `client_instance` only. No wildcards.
4. **Unpaired clients** MUST receive `deny` or `needs_approval`.
5. **A pass is necessary, not sufficient.** Every disclosure still requires 0.2 `context_request` → `policy_decision` → `scoped_context_bundle`. An active `context_pass` is not a bundle, wildcard selector, or ambient vault access.
6. **Categories grant; predicates select.** The pass grants `memory_category` values. The request still names `{ predicate }` selectors. An off-pass category MUST be denied or force `needs_approval` for the exact request.
7. **Ask ≠ read.** `needs_approval` is a successful protocol outcome. `approval_handle` MUST NOT include denied claim values, claim text, or vault payloads.
8. **Write approval ≠ read pass.** Committing a `memory_update_proposal` MUST NOT mint or widen a `context_pass`.
9. **Revocation is prospective.** Revoking a pass or pairing MUST prevent future bundles. It cannot un-disclose issued bundles.
10. **Lifecycle is content-free.** `lifecycle_event.payload_included` MUST be `false`.
11. **Evidence is not upgraded.** `inferred` MUST NOT be disclosed as `stated_by_user` or `direct_user_save`.
12. **Vault ≠ public profile.** Visibility `vault` MUST NOT appear on a public profile.

### Companion flow

```text
identity_assertion (not a grant)
-> client_pairing (exact client_instance)
-> context_pass (categories + purpose codes)
-> 0.2 request / decision / bundle
```

`needs_approval` returns `approval_handle` as success. Proposal commit MUST NOT mint a pass. `lifecycle_event` sits beside receipts and carries no content. `claim_annotation` rides beside claims until a 0.3 core revision.

`lifecycle_event.operation` stays exactly:

`pass.issued` | `pass.revoked` | `pairing.revoked` | `proposal.committed` | `bundle.issued` | `bundle.expired`

### Required tests

Schema-valid JSON is not a pass. A CL-Pass claim MUST publish results for T01–T10. The oracles are in [`test-vectors/cl-pass/VECTORS.md`](../../test-vectors/cl-pass/VECTORS.md).

| ID | Invariant |
| --- | --- |
| T01 | Identity is not a vault grant |
| T02 | Unpaired client: ask is not read |
| T03 | `purpose_code` absent from pass (no prefix match) |
| T04 | Off-pass category; denied text absent |
| T05 | Later on-pass read still needs a new request |
| T06 | Proposal commit does not mint or widen a pass |
| T07 | Revoked pass cannot obtain a later bundle |
| T08 | `lifecycle_event` is content-free |
| T09 | `inferred` is not emitted as `stated_by_user` |
| T10 | Visibility `vault` is absent from public-profile export |

## Pointers

| Artifact | Location |
| --- | --- |
| Companion pack | [`protocol/companions/0.3-draft/`](../../protocol/companions/0.3-draft/) |
| Companion spec | [`protocol/companions/0.3-draft/spec.md`](../../protocol/companions/0.3-draft/spec.md) |
| 0.2 ↔ 0.3 crosswalk | [`protocol/companions/0.3-draft/crosswalk.md`](../../protocol/companions/0.3-draft/crosswalk.md) |
| T01–T10 vectors | [`test-vectors/cl-pass/VECTORS.md`](../../test-vectors/cl-pass/VECTORS.md) |
| Closed Lite schemas | [`protocol/schemas/`](../../protocol/schemas/) |

## Non-goals

This repository ships Context Layer only. PCP, Legatus, and AAA are out of scope for this change.

Do not do any of the following in this proposal:

- Switchboard / Egoist adapter, SDK, OIDC, MCP, or type-name imports
- PCP grants
- Legatus envelope
- Live issuer
- Opening the five Lite schemas
- Wildcards for categories, purpose codes, or `client_instance`
- Un-disclosure of already issued bundles
- Relicensing the public repository from Apache-2.0 / CC BY 4.0 to MIT
88 changes: 88 additions & 0 deletions protocol/companions/0.3-draft/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Context Layer primitives addendum

Companion objects for `context-layer/0.3-draft`. A `context-layer/0.2-draft` deployment MAY negotiate the `CL-Pass` profile without opening the five CL-Core-Lite schemas.

Status: working draft. Not an adopted standard.

## What this is

Native Context Layer objects for:

- identity that is not a vault grant
- exact client pairing
- a standing category pass (necessary, not sufficient)
- closed memory categories above predicate selectors
- ask-without-read (`needs_approval` as success, plus `approval_handle`)
- write-commit that MUST NOT mint a read pass
- content-free lifecycle events
- claim evidence, visibility, category, and attribution (companion envelope; 0.3 field proposals)

This directory is spec, schemas, and examples. It is not runtime code.

## What this is not

- Not a patch to `context_request`, `policy_decision`, `scoped_context_bundle`, `memory_update_proposal`, or `receipt`. Those Lite schemas stay closed (`additionalProperties: false`).
- Not a restatement of 0.2-draft: purpose-bound requests, four-state policy, recipient-bound single-use bundles, proposal-only writeback, receipts, requester / recipient / `client_instance`, `onward_disclosure`, or selectors as `{ "predicate" }`. Those already exist. This addendum only adds what they do not cover.
- Not an Egoist AI Passport or Switchboard adapter, subset, client, or type import.

## Observed origin

Standing category grants, identity-without-memory, exact client pairing, ask as normal output, write-approval-is-not-read, and content-free lifecycle were observed in Egoist AI Passport / Switchboard. They are rewritten here as Context Layer objects. That system's types, tool names, authorization-scope strings, and packages are not imported. See [crosswalk.md](crosswalk.md).

## How it composes with 0.2-draft

```text
identity_assertion # not a context grant
client_pairing # exact client_instance; not a pass
|
v
context_pass # categories + purpose codes; necessary, not sufficient
|
v
context_request # 0.2; selectors remain predicates
|
v
policy_decision # 0.2 four-state; unchanged schema
|
+-- needs_approval --> approval_handle # success, not an error
|
+-- allow / allow_with_reductions --> scoped_context_bundle # 0.2
|
v
receipt # 0.2
optional memory_update_proposal
|
v
commit MUST NOT mint or widen a context_pass
lifecycle_event # content-free sync log beside receipts
claim_annotation # rides beside claims until 0.3
```

A consumer that holds only `identity_assertion` MUST NOT be issued a bundle and MUST NOT be treated as authorized to request vault disclosure.

`CL-Pass` evaluation uses existing 0.2 `reason_codes` (for example `PASS_MISSING`, `CATEGORY_NOT_ON_PASS`, `PAIRING_REQUIRED`). It does not add fields to Lite objects.

## Files

| Path | Role |
| --- | --- |
| [spec.md](spec.md) | Normative addendum: invariants, objects, lifecycles, 0.3-draft note, non-goals |
| [crosswalk.md](crosswalk.md) | Observed phrase → CL primitive. Not their protocol. |
| [schemas/](schemas/) | Closed JSON Schema 2020-12 companions |
| [examples/](examples/) | Synthetic objects valid against those schemas |

## Companion schemas

Required by this addendum:

- `schemas/context-pass.schema.json`
- `schemas/client-pairing.schema.json`
- `schemas/approval-handle.schema.json`
- `schemas/lifecycle-event.schema.json`

Also in this directory, because they are first-class companion objects:

- `schemas/identity-assertion.schema.json`
- `schemas/claim-annotation.schema.json`

All use `spec_version` `context-layer/0.3-draft` and `additionalProperties: false`.
26 changes: 26 additions & 0 deletions protocol/companions/0.3-draft/crosswalk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Observed phrase → Context Layer primitive

This table records where a behavior was observed, then names the CL object that encodes it. Observation is not adoption.

This addendum does **not** implement Egoist AI Passport, Switchboard, or any protocol from that system. It does not import their types, tool names, authorization-scope strings, or packages. A CL deployment that speaks these objects is not speaking that protocol.

| Observed phrase (Egoist / Switchboard) | CL primitive | What is lifted | What is not imported |
| --- | --- | --- | --- |
| Sign-in consent and memory consent are two consents | `identity_assertion` with `context_grant: false` | Authenticating a principal MUST NOT disclose vault claims. A consumer that only has identity MUST NOT call the vault. | Authorization-scope names, identity-provider token shapes, client metadata documents |
| Category pass: one app, one category, one duration | `context_pass` | Standing grant of `memory_category` values to one `principal` + `client_instance` until `expires_at` or revoke. Necessary, not sufficient. | Pass type names, duration defaults, app-id formats from that system |
| Preference, fact, project, instruction | `memory_category` enum | Closed grant layer above selectors. A pass grants categories. A request still names `{ "predicate" }` selectors. | Their category type names as imported types; predicates stay 0.2 selectors |
| Recall without a pass returns an approval link as normal output, not an error | `policy_decision.decision = needs_approval` (already 0.2) plus companion `approval_handle` | Ask is not read. `needs_approval` is a successful protocol outcome. Handle carries `pass_gap` and optional `user_visible_url`. MUST NOT include denied claim values. | Their approval URL format, tool names, or error-vs-result encoding |
| Approval does not grant read access | Invariant on `memory_update_proposal` commit | Committing a proposal MUST NOT mint or widen a `context_pass`. Read still requires an active pass and a new `context_request`. | Their write-approval records or store-tool semantics |
| Pair exact clients before grants | `client_pairing` | Exact `client_instance` admission. Unpaired clients MUST be `deny` or `needs_approval`. Pairing is not a pass. | Their client registry, metadata URL rules, or admission paths |
| Content-free lifecycle events, separate from deletable content | `lifecycle_event` | Syncable public-of-the-vault log: operation, refs, timestamps. NO claim text. NO payloads. Receipts remain 0.2 evidence. | Their sync wire format or event type names as imported enums |
| Evidence and visibility on stored items | `claim_annotation`; 0.3 field proposals on `context_claim` | `evidence_basis`, `visibility`, `category`, `attribution`. Public profile MUST NOT include vault-only claims. `inferred` MUST NOT be disclosed as `stated_by_user`. | Their item schemas, visibility flags, or inference labels as imported fields |

## How to read this

Left column: informal description of a behavior that existed elsewhere.

Middle: the CL object or invariant. New work is companion objects plus a 0.3-draft note. The five CL-Core-Lite schemas are not extended.

Right: reminder that a crosswalk is not a mapping of on-the-wire types.

If a deployment needs to interoperate with that other system, it MUST do so through an adapter that preserves CL invariants at the vault boundary. That adapter is out of scope here.
18 changes: 18 additions & 0 deletions protocol/companions/0.3-draft/examples/approval-handle.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"spec_version": "context-layer/0.3-draft",
"type": "approval_handle",
"id": "urn:cl:approval:ah_4401",
"created_at": "2026-08-28T18:10:00Z",
"issuer": {
"id": "urn:cl:approval-surface:local"
},
"request_ref": "urn:cl:request:req_880",
"decision_ref": "urn:cl:decision:dec_880",
"pass_gap": {
"missing_categories": [
"instruction"
]
},
"user_visible_url": "https://vault.example/approve/ah_4401",
"expires_at": "2026-08-28T18:40:00Z"
}
17 changes: 17 additions & 0 deletions protocol/companions/0.3-draft/examples/claim-annotation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"spec_version": "context-layer/0.3-draft",
"type": "claim_annotation",
"id": "urn:cl:annotation:ann_4401",
"created_at": "2026-08-28T17:55:00Z",
"issuer": {
"id": "urn:cl:annotator:local"
},
"claim_ref": "urn:cl:claim:pref-quiet-hours",
"evidence_basis": "direct_user_save",
"visibility": "vault",
"category": "preference",
"attribution": {
"via_principal": "urn:cl:principal:subject-primary",
"captured_at": "2026-08-28T17:54:50Z"
}
}
Loading
Loading