@prefig/upact 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/CONFORMANCE.md +162 -0
- package/CONTRIBUTING.md +87 -0
- package/GOVERNANCE.md +34 -0
- package/LICENSE +396 -0
- package/LICENSE-CODE +202 -0
- package/README.md +97 -0
- package/ROADMAP.md +107 -0
- package/SECURITY.md +33 -0
- package/SPEC.md +314 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +13 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +14 -0
- package/dist/internal.js.map +1 -0
- package/dist/runtime.d.ts +47 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +61 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +104 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +65 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project uses [semantic versioning](https://semver.org/) from v1.0.0 onward; v0.x breaking changes are permitted between minor versions.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## [0.1.1] — 2026-05-01
|
|
8
|
+
|
|
9
|
+
Additive spec amendments: lifecycle and provenance on `Upactor`. Ships `@prefig/upact-oidc` as the third reference adapter.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `IdentityLifecycle` type: `{ expires_at?: Date; renewable: 'reauth' | 'represence' | 'never' }`. Optional on `Upactor.lifecycle`; the OIDC adapter populates it from JWT `exp`. Non-OIDC adapters may omit it.
|
|
14
|
+
- `Upactor.provenance?: { substrate: string; instance?: string }` — cross-IDP disambiguation; the OIDC adapter populates it from the OIDC issuer URL. Optional; non-OIDC adapters may omit it.
|
|
15
|
+
- `@prefig/upact-oidc`: OIDC reference adapter. PKCE (S256), signed-cookie state, transparent session refresh, scope policy that structurally excludes `email` / `phone` / `address` / `groups` at construction time.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## [0.1.0] — 2026-05-01
|
|
20
|
+
|
|
21
|
+
First public draft. Establishes the `Upactor` primitive, the `IdentityPort` contract, the `AuthError` vocabulary, and the Session opacity guarantee. Ships with two reference adapters (`@prefig/upact-supabase`, `@prefig/upact-simplex`) and the five-test contributor audit.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- `Upactor` type: `{ id: string; display_hint?: string; capabilities: ReadonlySet<Capability> }` — the minimal port-facing identity object. Named to draw on the UML Actor lineage and the upact brand.
|
|
26
|
+
- `Capability` vocabulary: `'email' | 'recovery'` (audit-trimmed; extensible via §5.2 registry process at v0.2+).
|
|
27
|
+
- `IdentityPort` interface: `authenticate`, `currentUpactor`, `invalidate`, `issueRenewal`.
|
|
28
|
+
- `AuthError` and `AuthErrorCode`: normative six-member error vocabulary (`credential_invalid`, `credential_rejected`, `substrate_unavailable`, `identity_unavailable`, `rate_limited`, `auth_failed`).
|
|
29
|
+
- `Session` type and `createSession` factory: opaque runtime value that passes sixteen-vector reflection suite in `tests/runtime.test.ts`.
|
|
30
|
+
- `SubstrateUnavailableError`: typed error class for adapter-to-application substrate failure signalling.
|
|
31
|
+
- `SPEC.md`: first public draft, covering Upactor (§4), capability vocabulary (§5), port operations (§6), Session opacity and adapter conformance (§7), security considerations (§10), and the deferred-decisions register (§12).
|
|
32
|
+
- `CONTRIBUTING.md`: five-test contributor audit and AI-Involvement trailer convention.
|
|
33
|
+
- `GOVERNANCE.md`: v0.x maintainer posture and v1.0 working-group target.
|
|
34
|
+
- `CONFORMANCE.md`: conformance template with filled-in Supabase reference adapter example.
|
|
35
|
+
- `docs/adapter-shapes.md`: Supabase (enforcement camp) and SimpleX (pre-conforming) adapter shape sketches; OIDC forward-looking sketch for Phase C.
|
|
36
|
+
- `docs/cross-adapter-findings.md`: F1–F4, F6, G1 cross-substrate observations.
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- `UserIdentity` deprecated in favour of `Upactor`. The alias `UserIdentity = Upactor` remains for v0.1.x compatibility and will be removed in v0.2.
|
|
41
|
+
|
|
42
|
+
### Removed (from earlier drafts)
|
|
43
|
+
|
|
44
|
+
- Speculative capability vocabulary entries (`messaging`, `p2p_matching`, `presence`) — no concrete consumer per audit; SimpleX ships with `[]`.
|
|
45
|
+
- Convene, Reticulum, and fediverse-DID adapter sketches — no shipped adapter, no concrete consumer; return to `docs/adapter-shapes.md` when their adapters ship.
|
package/CONFORMANCE.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Conformance statement template
|
|
2
|
+
|
|
3
|
+
Copy this template into your adapter package as `CONFORMANCE.md` and fill in each section. A filled-in example for the Supabase reference adapter follows the template.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Template
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
# Conformance: <adapter package name>
|
|
11
|
+
|
|
12
|
+
**Spec version:** upact vX.Y
|
|
13
|
+
**Package version:** X.Y.Z
|
|
14
|
+
**Date:** YYYY-MM-DD
|
|
15
|
+
|
|
16
|
+
## Substrate
|
|
17
|
+
|
|
18
|
+
<Name and brief description of the substrate. Include whether it is enforcement-camp or pre-conforming.>
|
|
19
|
+
|
|
20
|
+
## Threat model
|
|
21
|
+
|
|
22
|
+
<What threat model does this adapter serve? See SPEC.md §10 for the taxonomy (casual coordination / anonymous-pseudonymous / adversarial-context). What does the substrate protect against, and what does it not protect against?>
|
|
23
|
+
|
|
24
|
+
## Capabilities self-declared
|
|
25
|
+
|
|
26
|
+
`[ <list of Capability values this adapter may return, or empty for []> ]`
|
|
27
|
+
|
|
28
|
+
For each capability listed, name the concrete consumer (the application code that gates on it).
|
|
29
|
+
|
|
30
|
+
## AuthError mapping table
|
|
31
|
+
|
|
32
|
+
| Substrate error | AuthErrorCode |
|
|
33
|
+
|---|---|
|
|
34
|
+
| <substrate error> | <code> |
|
|
35
|
+
|
|
36
|
+
## Session opacity
|
|
37
|
+
|
|
38
|
+
This adapter uses `createSession` from `@prefig/upact` for Session construction.
|
|
39
|
+
|
|
40
|
+
OR
|
|
41
|
+
|
|
42
|
+
This adapter does not use `createSession`. The adapter's Session implementation passes the sixteen-vector reflection test at `tests/back-channel.test.ts` (vectors: JSON.stringify, Object.keys, Object.getOwnPropertyNames, Reflect.ownKeys, Object.getOwnPropertySymbols, for-in, structuredClone, util.inspect, direct property access by name, Object spread, wrapped JSON.stringify, and cast access to common substrate-property names).
|
|
43
|
+
|
|
44
|
+
## Adapter back-channel closure
|
|
45
|
+
|
|
46
|
+
This adapter passes a sixteen-vector reflection test (`tests/back-channel.test.ts`) asserting that no sentinel substrate token leaks through the adapter instance.
|
|
47
|
+
|
|
48
|
+
## Deviations from SHOULD clauses
|
|
49
|
+
|
|
50
|
+
<List any SHOULD clauses from the spec that this adapter does not follow, and the reason. If none, write "None.">
|
|
51
|
+
|
|
52
|
+
## Identifier derivation
|
|
53
|
+
|
|
54
|
+
<Describe how the `Upactor.id` is derived from the substrate's user identifier. If it is a hashed derivation, name the hash function and any prefix truncation. If it is a direct mapping, explain why the substrate identifier is already opaque.>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Example: `@prefig/upact-supabase`
|
|
60
|
+
|
|
61
|
+
# Conformance: @prefig/upact-supabase
|
|
62
|
+
|
|
63
|
+
**Spec version:** upact v0.1
|
|
64
|
+
**Package version:** 0.1.0
|
|
65
|
+
**Date:** 2026-05-01
|
|
66
|
+
|
|
67
|
+
## Substrate
|
|
68
|
+
|
|
69
|
+
Supabase Auth — a managed PostgreSQL-backed identity service. `auth.users` is the substrate user record. Enforcement-camp substrate: the Supabase `User` object exposes email, phone, JWT claims, `app_metadata`, and `user_metadata`; the adapter strips all of these except what is needed to populate the three `Upactor` fields.
|
|
70
|
+
|
|
71
|
+
## Threat model
|
|
72
|
+
|
|
73
|
+
Casual coordination. Supabase Auth is a centralised service operated by Supabase, Inc. It is not appropriate for adversarial-context deployments where substrate-operator trust is not granted. The adapter is designed for applications where the substrate's leakiness is acceptable in exchange for Supabase's ergonomics and reliability.
|
|
74
|
+
|
|
75
|
+
## Capabilities self-declared
|
|
76
|
+
|
|
77
|
+
`['email', 'recovery']` — for users with a confirmed email address (non-empty `user.email`).
|
|
78
|
+
`[]` — for users without a confirmed email address.
|
|
79
|
+
|
|
80
|
+
Concrete consumer: dyad M1 UI gates on `capabilities.has('email')` to show or hide email-related settings. `recovery` is bundled with `email` because the same email address that identifies the user is the recovery channel; they are not independently affords.
|
|
81
|
+
|
|
82
|
+
## AuthError mapping table
|
|
83
|
+
|
|
84
|
+
| Substrate error | AuthErrorCode |
|
|
85
|
+
|---|---|
|
|
86
|
+
| `AuthApiError` (invalid credentials, wrong password) | `credential_rejected` |
|
|
87
|
+
| `AuthApiError` (user not found) | `credential_rejected` |
|
|
88
|
+
| `AuthApiError` (email not confirmed) | `credential_rejected` |
|
|
89
|
+
| `AuthApiError` (rate limit) | `rate_limited` |
|
|
90
|
+
| Network error / Supabase unreachable | `substrate_unavailable` |
|
|
91
|
+
| Malformed substrate User (no `id` field) | `auth_failed` |
|
|
92
|
+
| Unknown error | `auth_failed` |
|
|
93
|
+
|
|
94
|
+
Note: Supabase conflates "user not found" with "wrong password" as credential-stuffing resistance. Both surface as `credential_rejected`. `identity_unavailable` is not emitted by this adapter.
|
|
95
|
+
|
|
96
|
+
## Session opacity
|
|
97
|
+
|
|
98
|
+
This adapter uses `createSession` from `@prefig/upact` for Session construction.
|
|
99
|
+
|
|
100
|
+
## Adapter back-channel closure
|
|
101
|
+
|
|
102
|
+
This adapter passes a sixteen-vector reflection test at `tests/back-channel.test.ts`. Sentinel values for `__internalToken`, `__anonKey`, and `__url` on a mock `SupabaseClient` are verified unreachable through JSON.stringify, Object.keys, Object.getOwnPropertyNames, Reflect.ownKeys, Object.getOwnPropertySymbols, for-in, structuredClone, util.inspect, direct property access by name, Object spread, wrapped JSON.stringify, and cast access to `client`, `supabase`, `_client`.
|
|
103
|
+
|
|
104
|
+
## Deviations from SHOULD clauses
|
|
105
|
+
|
|
106
|
+
None.
|
|
107
|
+
|
|
108
|
+
## Identifier derivation
|
|
109
|
+
|
|
110
|
+
`Upactor.id` is set directly from `user.id` — the Supabase Auth UUID. Supabase UUIDs are opaque random identifiers (`gen_random_uuid()`); they are not derivable from user-supplied identifiers (email, phone). No hashing is applied. The raw UUID is not email-shaped and carries no information about the user visible at the application layer.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Example: `@prefig/upact-simplex`
|
|
115
|
+
|
|
116
|
+
# Conformance: @prefig/upact-simplex
|
|
117
|
+
|
|
118
|
+
**Spec version:** upact v0.1
|
|
119
|
+
**Package version:** 0.1.0
|
|
120
|
+
**Date:** 2026-05-01
|
|
121
|
+
|
|
122
|
+
## Substrate
|
|
123
|
+
|
|
124
|
+
SimpleX Chat daemon — a local IPC process exposing a JSON command API. Pre-conforming substrate: the SimpleX local profile carries `localDisplayName`, `agentUserId` (UUID), and a handful of status flags. There is no central directory; profiles are application-scoped and anonymous. The adapter is thin — mostly type translation.
|
|
125
|
+
|
|
126
|
+
## Threat model
|
|
127
|
+
|
|
128
|
+
Anonymous / pseudonymous coordination. The SimpleX substrate has no central directory and uses anonymous unidirectional queues. The substrate's natural shape is already aligned with upact's privacy minima. This adapter is appropriate for deployments where pseudonymity is a requirement and correlation across sessions is undesirable.
|
|
129
|
+
|
|
130
|
+
## Capabilities self-declared
|
|
131
|
+
|
|
132
|
+
`[]` — no capabilities declared for v0.1.
|
|
133
|
+
|
|
134
|
+
The SimpleX substrate affords messaging (`sendMessage`, `receiveMessage`) and peer-to-peer matching. Neither is surfaced through the upact port at v0.1: no shipped consumer gates on a `messaging` or `p2p_matching` capability check. Per the minimum-viable discipline (CONTRIBUTING.md), capabilities land when a concrete consumer surfaces them.
|
|
135
|
+
|
|
136
|
+
## AuthError mapping table
|
|
137
|
+
|
|
138
|
+
| Substrate error | AuthErrorCode |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `DaemonError { kind: 'unreachable' }` | `substrate_unavailable` |
|
|
141
|
+
| `DaemonError { kind: 'not-found' }` | `identity_unavailable` |
|
|
142
|
+
| `DaemonError { kind: 'rejected' }` | `credential_rejected` |
|
|
143
|
+
| `DaemonError { kind: 'invalid-profile' }` | `credential_invalid` |
|
|
144
|
+
| `DaemonError { kind: 'unknown' }` | `auth_failed` |
|
|
145
|
+
| Unknown error | `auth_failed` |
|
|
146
|
+
| Malformed substrate User (no `agentUserId`) | `auth_failed` |
|
|
147
|
+
|
|
148
|
+
## Session opacity
|
|
149
|
+
|
|
150
|
+
This adapter uses `createSession` from `@prefig/upact` for Session construction.
|
|
151
|
+
|
|
152
|
+
## Adapter back-channel closure
|
|
153
|
+
|
|
154
|
+
This adapter passes a sixteen-vector reflection test at `tests/back-channel.test.ts`. Sentinel values for `__internalToken`, `__socketPath`, and `__profileData` on a mock `SimpleXClient` are verified unreachable through all standard reflection vectors and cast access to `client`, `simpleXClient`, `_client`.
|
|
155
|
+
|
|
156
|
+
## Deviations from SHOULD clauses
|
|
157
|
+
|
|
158
|
+
None.
|
|
159
|
+
|
|
160
|
+
## Identifier derivation
|
|
161
|
+
|
|
162
|
+
`Upactor.id` is derived from `user.agentUserId` (a UUID string) via `SHA-256(agentUserId).slice(0, 32)` — the first 32 hex characters of the SHA-256 digest. The derivation is deterministic per `agentUserId` (stable across sessions for the same profile) and not reversible from the application layer. The hash is implemented with the Web Crypto API (`crypto.subtle.digest`).
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Contributing to upact
|
|
2
|
+
|
|
3
|
+
## How the spec grows
|
|
4
|
+
|
|
5
|
+
upact operates on **inverse kinematics**: the spec grows from concrete consumer need, not from speculative design. A change to `SPEC.md`, `src/types.ts`, or the capability vocabulary begins with an adapter author or application developer who needs something the current spec does not provide — not the other way around.
|
|
6
|
+
|
|
7
|
+
Before proposing a spec change, run the five-test audit below. All five tests apply; a change that fails any one does not land.
|
|
8
|
+
|
|
9
|
+
### The five-test audit
|
|
10
|
+
|
|
11
|
+
**1. Concrete-need.** Does a shipped or actively-in-development adapter *require* this change to function correctly? "Would be useful for" is not sufficient. Name the adapter and the specific operation that fails without the change.
|
|
12
|
+
|
|
13
|
+
**2. Minimum-viable.** Is this the smallest change to the spec (types, MUST clauses, capability vocabulary) that satisfies the concrete need? If a narrower change would work, make that one instead.
|
|
14
|
+
|
|
15
|
+
**3. Substrate-agnosticism.** Does the change make sense for at least two structurally different substrates — one enforcement-camp, one pre-conforming (see `docs/adapter-shapes.md`)? A change that only works for one substrate shape is a substrate-specific extension, not a spec change.
|
|
16
|
+
|
|
17
|
+
**4. Binding-integrity.** Does the change preserve the self-binding contract? Spec changes MUST NOT:
|
|
18
|
+
- Expose additional substrate fields through the port (email, phone, IP, substrate-internal handles)
|
|
19
|
+
- Add OPTIONAL fields to `Upactor` whose presence reveals substrate-type information to the application
|
|
20
|
+
- Weaken the Session opacity guarantee (§7.4)
|
|
21
|
+
- Weaken the adapter back-channel closure requirement (§7.5)
|
|
22
|
+
|
|
23
|
+
**5. Disclosure.** Does the change require documentation of a new disclosure obligation for conforming adapters — in the conformance statement (§9), the security considerations (§10), or the deferred-decisions register (§12)?
|
|
24
|
+
|
|
25
|
+
### Worked example: adding `lifecycle`
|
|
26
|
+
|
|
27
|
+
When `lifecycle: { expires_at?: number; renewable: ... }` was first proposed for `Upactor`, the audit looked like this:
|
|
28
|
+
|
|
29
|
+
- **Concrete-need:** OIDC adapter needs `jwt.exp` for cookie renewal decisions. Named consumer: dyad M2 SvelteKit layout, `+layout.server.ts` session check. — *passes.*
|
|
30
|
+
- **Minimum-viable:** Could the adapter just re-call `issueRenewal` instead? Yes, for dyad M2. The field is pre-emptive. — *fails.*
|
|
31
|
+
- **Result:** Deferred to §12 (D-SPEC-4). Returns when the OIDC adapter concretely needs it.
|
|
32
|
+
|
|
33
|
+
### Worked example: SimpleX `messaging` capability
|
|
34
|
+
|
|
35
|
+
When `messaging` was proposed as a capability for `@prefig/upact-simplex`:
|
|
36
|
+
|
|
37
|
+
- **Concrete-need:** SimpleX affords messaging. No current dyad UI gates on `capabilities.has('messaging')`. No shipped consumer. — *fails.*
|
|
38
|
+
- **Result:** `@prefig/upact-simplex` ships with `capabilities = []`. Capability lands when a consumer surfaces.
|
|
39
|
+
|
|
40
|
+
## Adapter conformance
|
|
41
|
+
|
|
42
|
+
New adapters MUST pass the five-test audit for any spec amendment their design requires. Adapters that work within the existing spec need not run the audit — the spec is already there.
|
|
43
|
+
|
|
44
|
+
All adapters MUST:
|
|
45
|
+
|
|
46
|
+
1. Ship a `CONFORMANCE.md` (template in this repo) declaring the spec version, substrate, threat model, capability self-declaration, and `AuthError` mapping table.
|
|
47
|
+
2. Ship a sixteen-vector reflection test (see `@prefig/upact-supabase/tests/back-channel.test.ts`) asserting that no sentinel substrate token leaks through the adapter instance.
|
|
48
|
+
3. Use `createSession` from `@prefig/upact` for Session construction, or pass an equivalent sixteen-vector test suite.
|
|
49
|
+
|
|
50
|
+
## AI-Involvement trailers
|
|
51
|
+
|
|
52
|
+
upact acknowledges LLM contributions to normative content under an `AI-Involvement` trailer on git commits. The trailer records the character of AI involvement so readers can calibrate the provenance of what they are reading.
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
AI-Involvement: <tier>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Five tiers:
|
|
59
|
+
|
|
60
|
+
| Tier | When to use |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `autonomous` | AI generated the full commit with no human review of content (rare; avoid for normative paths) |
|
|
63
|
+
| `authored` | AI wrote the primary content; human reviewed and accepted with minor edits |
|
|
64
|
+
| `collaborative` | Human and AI contributed substantial portions; hard to separate authorship |
|
|
65
|
+
| `assisted` | Human wrote the primary content; AI provided suggestions or structured material the human evaluated |
|
|
66
|
+
| `commit-message-only` | AI wrote only the commit message; content is human-authored |
|
|
67
|
+
|
|
68
|
+
The trailer is advisory, not mechanical. Its purpose is honest attribution, not compliance theatre. Use the tier that most accurately describes the commit.
|
|
69
|
+
|
|
70
|
+
Normative paths (`SPEC.md`, `src/types.ts`, capability vocabulary) that carry `autonomous` or `authored` tiers are permitted at v0.1. This posture is revisited before v1.0.
|
|
71
|
+
|
|
72
|
+
## Spec versioning and stability
|
|
73
|
+
|
|
74
|
+
- v0.x: breaking changes between minor versions are permitted. The maintainer (Theodore Evans) makes decisions.
|
|
75
|
+
- v1.0: first stable version. Decisions about the core capability vocabulary (§5.1) and MUST clauses (§7) move to a working group of ≥3 conforming-adapter authors. See `GOVERNANCE.md`.
|
|
76
|
+
|
|
77
|
+
## What goes in the deferred-decisions register
|
|
78
|
+
|
|
79
|
+
`SPEC.md §12` is the register of features that passed the concrete-need test *eventually* — meaning a concrete need exists in principle — but failed minimum-viable or substrate-agnosticism, or whose consumer is not yet shipped. Items enter the register with a brief rationale; they reactivate when the consumer surfaces or a shipped adapter forces the question.
|
|
80
|
+
|
|
81
|
+
Do not treat §12 entries as a backlog. They are a deliberate holding pattern, not a roadmap.
|
|
82
|
+
|
|
83
|
+
## Submissions
|
|
84
|
+
|
|
85
|
+
- Open an issue before a PR for anything that touches `SPEC.md` or `src/types.ts`.
|
|
86
|
+
- Adapter packages are independent repos under the `@prefig/` namespace; open issues on the relevant adapter repo.
|
|
87
|
+
- Discussion happens in issues. Normative decisions land in commits. The commit message carries the decision; the issue carries the context.
|
package/GOVERNANCE.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Governance
|
|
2
|
+
|
|
3
|
+
## v0.x (current)
|
|
4
|
+
|
|
5
|
+
Theodore Evans is the maintainer. Decisions about the spec, capability vocabulary, and normative content are made by the maintainer, informed by adapter authors and application developers through issues and PRs.
|
|
6
|
+
|
|
7
|
+
The inverse-kinematics principle (see `CONTRIBUTING.md`) is the primary constraint on spec growth. The maintainer applies it consistently; so should anyone making a case for a change.
|
|
8
|
+
|
|
9
|
+
Decisions are recorded in commits to `SPEC.md` and `ROADMAP.md`, not in issue threads. Issue threads carry context; the commit is the decision.
|
|
10
|
+
|
|
11
|
+
## v1.0 (target)
|
|
12
|
+
|
|
13
|
+
Decisions about the core capability vocabulary (§5.1) and MUST clauses (§7) move to a working group of ≥3 conforming-adapter authors at v1.0. A *conforming-adapter author* is an organisation or individual who:
|
|
14
|
+
|
|
15
|
+
- Maintains a published `@prefig/upact-*` package that passes the sixteen-vector reflection test,
|
|
16
|
+
- has shipped a `CONFORMANCE.md` against a specific version of the spec, and
|
|
17
|
+
- is actively maintaining the adapter (a PR or release in the last twelve months).
|
|
18
|
+
|
|
19
|
+
The working group operates on rough consensus. When rough consensus is absent, the maintainer retains casting vote.
|
|
20
|
+
|
|
21
|
+
Additions to the capability vocabulary after v1.0 require a working group decision AND demonstration of:
|
|
22
|
+
|
|
23
|
+
1. Implementation by ≥2 independent conforming adapters, and
|
|
24
|
+
2. Consumption by ≥1 shipped application.
|
|
25
|
+
|
|
26
|
+
Changes to MUST clauses require the same bar plus a migration period during which the old behaviour remains valid.
|
|
27
|
+
|
|
28
|
+
## Forks
|
|
29
|
+
|
|
30
|
+
upact is dual-licensed (CC BY 4.0 / Apache-2.0; see `LICENSE` and `LICENSE-CODE`). Forks are permitted; they are asked to rename the package to avoid registry confusion. Forked packages that claim upact conformance MUST reference the specific version of the spec they conform to in their `CONFORMANCE.md`.
|
|
31
|
+
|
|
32
|
+
## Conflicts
|
|
33
|
+
|
|
34
|
+
Disputes about spec interpretation go to the issue tracker. The maintainer resolves them by issuing a normative clarification (a commit to `SPEC.md`). Disputes about governance itself go to the working group at v1.0; before v1.0, they go to the maintainer.
|