@nullsquare/agent-authority 0.4.4 → 0.4.6

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/ROADMAP.md CHANGED
@@ -1,26 +1,64 @@
1
1
  # Agent Authority Roadmap
2
2
 
3
- Agent Authority is implementation-first. We are not trying to invent a new authentication protocol or policy language.
3
+ Agent Authority is implementation-first, but the current bottleneck is now **product proof**, not another authorization subsystem.
4
4
 
5
- The product thesis we are validating is:
5
+ The product thesis is:
6
6
 
7
7
  > **Give an agent a task, not standing account permissions.**
8
8
 
9
- A human-approved task becomes temporary execution authority. As the agent discovers concrete resources through authorized work, authority may follow those resources through provenance-bound facts, but it may never silently broaden.
9
+ The differentiated mechanism is:
10
10
 
11
- ## Current invariant
11
+ > **Authority may follow exact resources discovered through already-authorized execution, without becoming ambient account authority.**
12
+
13
+ ## Core invariant
12
14
 
13
15
  ```text
14
16
  Task Lease authority <= Mission authority
15
17
  ```
16
18
 
17
- Across delegation and integrations:
19
+ Across delegation, transports and durable state:
18
20
 
19
21
  ```text
20
22
  authority may stay the same or shrink
21
23
  never silently grow
22
24
  ```
23
25
 
26
+ ## P0 — Task-first product proof — current priority
27
+
28
+ The engine has enough depth to test whether developers actually want this layer. Product work now outranks additional distributed/crypto infrastructure unless a real workflow proves the missing infrastructure is blocking adoption or safety.
29
+
30
+ - [x] task-first facade over Mission + Task Lease + Guard
31
+ - [x] explicit service permissions without requiring hand-authored Mission JSON
32
+ - [x] named task authority roots
33
+ - [x] `task.run()` guarded effect boundary
34
+ - [x] `task.authorityFrom()` strict evidence-derived authority
35
+ - [x] task-first binding of named authority to later effects
36
+ - [x] human-readable authority-delta explanation
37
+ - [x] same task-first calls can opt into durable local state by adding a store
38
+ - [x] self-contained GitHub-shaped task-first demo
39
+ - [x] deterministic utility regression benchmark
40
+ - [ ] coding workflow: issue -> branch -> files -> PR, with merge/deploy outside authority
41
+ - [ ] support/communications workflow: email -> customer -> meeting/CRM/reply target
42
+ - [ ] operations/finance workflow: ticket -> order -> payment -> bounded refund
43
+ - [ ] first-time developer can complete a meaningful integration in under 10 minutes
44
+ - [ ] at least one external developer adopts the package without project-author assistance
45
+
46
+ Current utility regression metrics:
47
+
48
+ ```text
49
+ normal task completion rate
50
+ false approval rate
51
+ true authority-delta step-up rate
52
+ unauthorized effect rate
53
+ provider effects per completed task
54
+ ```
55
+
56
+ The deterministic fixture target is 100% normal completion, 0% false approvals, 100% true-delta step-up and 0% unauthorized effects. It is a regression fixture, not a real-world benchmark.
57
+
58
+ See `docs/product-proof.md`.
59
+
60
+ **Product gate:** do not prioritize deeper distributed persistence, provider-attestation protocols, new token formats, broad OAuth platform work, A2A, a policy DSL, another MCP control plane, or connector-count expansion until the product proof moves or a concrete workflow shows one of those items is necessary.
61
+
24
62
  ## M0 — Enforcement foundation — complete
25
63
 
26
64
  - [x] mission validation
@@ -31,7 +69,7 @@ never silently grow
31
69
  - [x] delegation attenuation
32
70
  - [x] mission revocation
33
71
  - [x] action receipts and request hashes
34
- - [x] protocol-neutral `guard.run()` enforcement
72
+ - [x] protocol-neutral guard enforcement
35
73
  - [x] one-time approvals
36
74
  - [x] mutation idempotency
37
75
  - [x] short-lived local agent-instance auth
@@ -41,124 +79,128 @@ never silently grow
41
79
  - [x] harness-managed connector grant proof
42
80
  - [x] Node 20/22 CI, coverage, package checks and CodeQL
43
81
 
44
- ## M1 — Task Lease / derived-authority proof — current
82
+ ## M1 — Task Lease / derived-authority proof — implementation established
45
83
 
46
- - [x] Task Lease object around an existing mission
84
+ - [x] Task Lease around an existing Mission
47
85
  - [x] explicit authority roots
48
- - [x] derived facts anchored to same-mission `ALLOW` receipts
86
+ - [x] derived facts anchored to same-Mission ALLOW receipts
49
87
  - [x] parent-fact lineage
50
88
  - [x] exact context-field bindings
51
89
  - [x] unresolved facts fail closed
52
- - [x] resource mismatch becomes an authority-delta step-up signal
53
- - [x] explicit mission deny remains the ceiling
90
+ - [x] resource mismatch becomes an authority-delta step-up
91
+ - [x] explicit Mission deny remains the ceiling
54
92
  - [x] task completion immediately removes authority
55
- - [x] independent task-lease expiry
56
- - [x] task-lease ID/hash in receipts
57
- - [x] self-contained cross-system demo: Gmail-thread fact -> Calendar attendee
58
- - [x] reusable Google REST adapter for Gmail thread reads and Calendar event mutations
59
- - [x] adversarial Gmail -> Calendar test proving unrelated and post-completion effects never invoke provider callbacks
60
- - [x] real connected-account smoke: Gmail self-test fixture -> exact attendee -> temporary Calendar event -> cleanup
61
- - [ ] rerun the same proof as a public GitHub Actions job after repository Google OAuth secrets are configured
62
-
63
- **Success criterion:** a real multi-step agent workflow discovers a resource during an authorized read and can use exactly that resource in a later side effect, while an unrelated resource is technically blocked without requiring approval for every normal task step.
64
-
65
- The core cross-provider behavior is now implemented and exercised against connected Gmail and Calendar accounts. Public Actions reproducibility remains the final M1 evidence gate because GitHub cannot reuse an interactive ChatGPT connector credential; the manual workflow is committed and expects a refresh token stored only as repository secrets.
66
-
67
- ## M2 — Durable task execution
68
-
69
- Build only what the real M1 workflow proves necessary.
70
-
71
- - [ ] durable Task Lease persistence/recovery
72
- - [ ] atomic fact/binding updates
73
- - [ ] approved authority delta can safely attenuate/update a live lease
74
- - [ ] completion state survives process restart
75
- - [ ] durable lineage query: why was this exact action authorized?
76
- - [ ] concurrency tests for multiple agent workers operating under one lease
77
-
78
- **Success criterion:** a Task Lease survives daemon/process restarts without gaining authority or losing its provenance lineage.
93
+ - [x] independent Task Lease expiry
94
+ - [x] Task Lease ID/hash in receipts
95
+ - [x] self-contained Gmail-thread -> Calendar-attendee demo
96
+ - [x] reusable Google Gmail/Calendar adapter
97
+ - [x] adversarial Gmail -> Calendar zero-provider-call tests
98
+ - [x] connected-account Gmail -> Calendar smoke proof
99
+ - [ ] public GitHub Actions Gmail -> Calendar proof after repository OAuth secrets are configured
100
+
101
+ **Success criterion:** an authorized read can establish exactly one later resource as task authority while an unrelated resource is technically blocked without requiring approval for every normal task step.
102
+
103
+ The implementation criterion is met. Public Actions reproducibility remains a separate evidence gate because the interactive Google connector credential cannot be reused as repository secrets.
104
+
105
+ ## M2 — Durable task execution — local durable session established
106
+
107
+ - [x] authenticated local Task Lease persistence/recovery
108
+ - [x] exact Mission-hash binding on recovery
109
+ - [x] atomic authenticated fact/binding/status transaction primitive
110
+ - [x] stale-writer compare-and-swap protection
111
+ - [x] local per-lease transaction lock
112
+ - [x] mission-alias hardening inside transactions
113
+ - [x] automatic durable Task Lease session
114
+ - [x] security-critical session refresh before authority evaluation
115
+ - [x] durable completion/expiry across restart
116
+ - [ ] approved authority delta safely updates a live durable task
117
+ - [ ] durable lineage query for one exact authorization decision
118
+ - [ ] stronger multi-process stress/recovery tooling
119
+ - [ ] crash-safe remote-effect/receipt/state coupling
120
+
121
+ The existing local durability layer is sufficient for product proof. The unchecked items remain research/follow-on work unless a real workflow demonstrates that they block useful adoption or safety.
122
+
123
+ **Success criterion:** restart and cooperating local workers do not expand authority or silently overwrite newer task state. This is established for the reference local backend.
79
124
 
80
125
  ## M3 — Trustworthy derived facts — two-provider proof established
81
126
 
82
- The first real Gmail -> Calendar integration showed that recording a host-supplied value plus selector was too weak for the strongest derived-authority claim. The compatibility `derive()` path remains host-trusted; new provider work should prefer execution-bound evidence and reviewed adapter extractors.
83
-
84
- - [x] define a small trusted-adapter extractor contract for authority-relevant normalized provider fields
85
- - [x] bind successful guarded outputs to the exact ALLOW receipt, request and output hash
86
- - [x] add `TaskLease.deriveFromEvidence()` so the caller cannot provide the authority value
87
- - [x] migrate Gmail sender -> Calendar attendee derivation to the evidence-verified path
88
- - [x] migrate the real GitHub issue discovery -> comment mutation proof to the same evidence-verified path
89
- - [x] adversarial tests for value substitution, output/evidence tampering, receipt replay, cross-lease reuse, wrong-operation extraction and dangerous selectors
90
- - [x] shared conformance fixtures for reviewed operation -> authority-field mappings across Google and GitHub
91
- - [ ] define provider/result attestation stronger than a trusted host output hash where practical
92
- - [ ] define freshness/invalidation rules when a source resource changes
93
-
94
- The shared contract is documented in `docs/authority-extractor-conformance.md`. Google and GitHub now use the same `guard.run()` -> execution evidence -> reviewed extractor -> `deriveFromEvidence()` primitive, and the same conformance suite attacks both mappings.
95
-
96
- Do **not** build a general semantic policy language unless real integrations require it.
127
+ - [x] reviewed adapter extractor contract
128
+ - [x] successful guarded output bound to exact ALLOW receipt/request/output hash
129
+ - [x] strict `deriveFromEvidence()` where caller cannot provide the authority value
130
+ - [x] Gmail sender -> Calendar attendee strict derivation
131
+ - [x] GitHub issue discovery -> comment strict derivation
132
+ - [x] substitution/tamper/replay/cross-lease/wrong-operation/dangerous-selector tests
133
+ - [x] shared Google/GitHub authority-extractor conformance fixtures
134
+ - [ ] stronger provider/result attestation where a real provider makes it practical
135
+ - [ ] source freshness/invalidation semantics where a real workflow requires it
97
136
 
98
- **Success criterion:** provider-derived authority cannot be established through the strict path unless the exact guarded output, ALLOW receipt and reviewed extractor contract agree on the selected value. This behavior is now exercised across two provider mappings. Stronger provider attestation and source invalidation remain separate follow-on problems.
137
+ Do **not** build a general semantic policy language around this primitive.
99
138
 
100
- ## M4 Same task, multiple transports first proof established
139
+ **Success criterion:** strict provider-derived authority requires agreement between the exact guarded output, ALLOW receipt and reviewed extractor. This is demonstrated across Google and GitHub.
101
140
 
102
- Prove Agent Authority is not an MCP product or SDK wrapper.
141
+ ## M4 Same task, multiple transports complete
103
142
 
104
- - [x] same Task Lease through ordinary `guard.run()` SDK call
143
+ - [x] same Task Lease through direct guard/SDK execution
105
144
  - [x] same Task Lease through MCP gateway
106
145
  - [x] same Task Lease through brokered provider execution
107
- - [ ] at least one non-bypassable harness/tool-middleware integration
108
- - [x] interoperability test vectors across transports
146
+ - [x] real Vercel AI SDK protected-tool path
147
+ - [x] interoperability/adversarial vectors across transports
109
148
 
110
- `test/transport-invariance.test.js` establishes one `execution-evidence-v1` derived fact from brokered execution, then reuses that exact Task Lease and fact through direct SDK, MCP and brokered execution. The three paths produce the same `allow`, `authority_delta_required` and `task_lease_completed` outcomes, and blocked attempts execute zero host callbacks, MCP upstream calls or brokered provider operations.
149
+ Changing transport or configured harness execution path does not expand task authority in the demonstrated paths.
111
150
 
112
- Brokered Task Lease execution deliberately does not consume mission-level one-time approval to override a lease-level authority delta. Updating a live Task Lease after explicit approval remains separate M2 work.
151
+ ## M5 Adoption UX follows product proof, not infrastructure breadth
113
152
 
114
- **Success criterion:** changing transport or harness does not expand the task's authority. The SDK/MCP/broker portion is now demonstrated in-process; an external non-bypassable harness/tool-middleware integration remains the final M4 proof.
153
+ Prioritize only the UX needed by successful P0 workflows.
115
154
 
116
- ## M5 — Production credential and approval UX
117
-
118
- Only after the task-bound enforcement model is validated.
119
-
120
- - [ ] GitHub browser/App onboarding instead of token-stdin
121
- - [ ] reusable OAuth/OIDC connection engine
122
- - [ ] OS keychain / KMS-backed secret backend
123
- - [ ] automatic short-lived agent session bootstrap
124
155
  - [ ] compact approval UI showing the exact authority delta
125
- - [ ] signed receipt experiment
156
+ - [ ] one low-friction real provider onboarding path
157
+ - [ ] automatic short-lived agent session bootstrap where needed
158
+ - [ ] framework integration starter focused on task-first API
159
+ - [ ] external-developer quickstart feedback loop
126
160
 
127
- **Success criterion:** an external developer can install Agent Authority, connect one real provider, authorize one task, and complete it without exposing a long-lived credential to the model.
161
+ Items such as reusable OAuth/OIDC engines, KMS backends and signed-receipt experiments remain optional until product usage justifies them.
128
162
 
129
- ## M6 Ecosystem and contribution layer
163
+ **Success criterion:** an external developer can install Agent Authority, connect one real provider, authorize one meaningful task and complete it without exposing a long-lived credential to the model or learning the internal authority machinery first.
130
164
 
131
- - [ ] adapter/conformance starter template
132
- - [ ] framework integration examples
133
- - [ ] `good first issue` tasks based on real mappings/tests
134
- - [ ] independent contributor implementation of one adapter
135
- - [x] release packaging and npm publication
136
- - [ ] documentation site only when README/docs become too large
165
+ ## M6 Ecosystem only after repeatable adoption
137
166
 
138
- ## M7 Standards interoperability
167
+ - [ ] adapter/conformance starter template
168
+ - [ ] framework examples driven by real user requests
169
+ - [ ] good-first-issue tasks based on proven workflows
170
+ - [ ] independent contributor implementation of one mapping/adapter
171
+ - [x] npm release packaging and registry verification
172
+ - [ ] documentation site only when the current README/docs become genuinely limiting
139
173
 
140
- Only after operational evidence.
174
+ ## M7 — Standards interoperability only after operational evidence
141
175
 
142
176
  - [ ] map Task Lease concepts to emerging task/intent authorization work
143
177
  - [ ] accept external authorization envelopes where useful
144
178
  - [ ] avoid creating a competing identity/token standard
145
- - [ ] publish stable test vectors for non-amplification and authority lineage
146
- - [ ] evaluate an appropriate standards venue only if multiple independent implementations exist
147
-
148
- ## What we are not prioritizing
149
-
150
- - another agent harness
151
- - a new OAuth replacement
152
- - an MCP replacement
153
- - a giant connector marketplace
154
- - a proprietary universal policy DSL
155
- - a dashboard-first enterprise product
156
- - A2A support before task-bound tool execution is validated
179
+ - [ ] publish stable non-amplification/authority-lineage test vectors
180
+ - [ ] evaluate standards participation only after independent implementations/users exist
181
+
182
+ ## Freeze list
183
+
184
+ Unless a real workflow proves one is necessary now:
185
+
186
+ - distributed Task Lease databases
187
+ - generic storage abstraction layers
188
+ - provider-signed attestation protocol design
189
+ - new token or identity formats
190
+ - a general delegation protocol
191
+ - proprietary universal policy DSL
192
+ - broad OAuth platform work
193
+ - another MCP control plane
194
+ - A2A protocol implementation
195
+ - connector-count expansion for its own sake
196
+ - full distributed transactions across arbitrary remote providers
197
+ - dashboard-first enterprise product work
157
198
 
158
199
  ## Research questions
159
200
 
160
- 1. What provider-side or transport-side evidence can strengthen output integrity without turning Agent Authority into an attestation protocol?
161
- 2. How should an approved authority delta update a running task without opening a broader wildcard permission?
162
- 3. How should source-data changes invalidate downstream derived authority?
163
- 4. What provider/tool metadata is required to map operations to resource context reliably?
164
- 5. Can the same non-amplification conformance suite work across SDK, MCP, CLI and brokered execution?
201
+ 1. Can a first-time developer understand and integrate the task-first model in under 10 minutes?
202
+ 2. Which real workflows benefit enough from derived authority that an `if` statement is no longer sufficient?
203
+ 3. Where does Agent Authority create unnecessary approval friction or reduce useful task completion?
204
+ 4. How should an explicitly approved authority delta update a running task without opening wildcard authority?
205
+ 5. Which source-data changes actually require downstream authority invalidation in real workflows?
206
+ 6. What remote-effect coupling is necessary in practice, and which providers already offer idempotency/transaction primitives we can reuse instead of inventing our own protocol?
@@ -0,0 +1,130 @@
1
+ import { createTask } from '../src/task.js';
2
+ import { AuthorityApprovalRequiredError } from '../src/guard.js';
3
+
4
+ const NORMAL_TASKS = 40;
5
+ const DELTA_ATTACKS = 10;
6
+
7
+ function selectedItemExtractor({ receipt, output } = {}) {
8
+ if (receipt?.service !== 'demo' || receipt?.action !== 'item.discover') {
9
+ const error = new Error('wrong operation');
10
+ error.code = 'trusted_extractor_operation_mismatch';
11
+ throw error;
12
+ }
13
+ if (typeof output?.selected_item !== 'string') {
14
+ const error = new Error('invalid selected item');
15
+ error.code = 'trusted_extractor_output_invalid';
16
+ throw error;
17
+ }
18
+ return { extractor_id: 'benchmark.selected-item.v1', selector: 'output.selected_item' };
19
+ }
20
+
21
+ function newTask(index) {
22
+ const catalog = `catalog:${index}`;
23
+ return {
24
+ catalog,
25
+ task: createTask({
26
+ principal: 'user:benchmark',
27
+ agent: 'agent:benchmark',
28
+ request: `Discover and update the selected item for benchmark task ${index}`,
29
+ permissions: {
30
+ demo: {
31
+ allow: ['item.discover', 'item.update'],
32
+ deny: ['item.delete'],
33
+ constraints: { catalog: [catalog] }
34
+ }
35
+ },
36
+ authority: {
37
+ catalog: { kind: 'demo.catalog', value: catalog }
38
+ },
39
+ bindings: [
40
+ { service: 'demo', action: 'item.discover', field: 'catalog', authority: 'catalog' },
41
+ { service: 'demo', action: 'item.update', field: 'catalog', authority: 'catalog' }
42
+ ]
43
+ })
44
+ };
45
+ }
46
+
47
+ const metrics = {
48
+ normal_tasks: NORMAL_TASKS,
49
+ completed_normal_tasks: 0,
50
+ normal_approval_interruptions: 0,
51
+ delta_attacks: DELTA_ATTACKS,
52
+ delta_step_ups: 0,
53
+ unauthorized_effects: 0,
54
+ provider_effects: 0
55
+ };
56
+
57
+ for (let index = 0; index < NORMAL_TASKS; index += 1) {
58
+ const { task, catalog } = newTask(index);
59
+ const item = `item:${index}`;
60
+
61
+ const discovery = await task.run({
62
+ service: 'demo',
63
+ action: 'item.discover',
64
+ context: { catalog }
65
+ }, async () => {
66
+ metrics.provider_effects += 1;
67
+ return { selected_item: item };
68
+ });
69
+
70
+ task.authorityFrom(discovery, {
71
+ name: 'item',
72
+ kind: 'demo.item',
73
+ from: 'catalog',
74
+ extractor: selectedItemExtractor
75
+ });
76
+ task.bind({ service: 'demo', action: 'item.update', field: 'item', authority: 'item' });
77
+
78
+ try {
79
+ await task.run({
80
+ service: 'demo',
81
+ action: 'item.update',
82
+ context: { catalog, item }
83
+ }, async () => {
84
+ metrics.provider_effects += 1;
85
+ return { updated: item };
86
+ });
87
+ metrics.completed_normal_tasks += 1;
88
+ } catch (error) {
89
+ if (error instanceof AuthorityApprovalRequiredError) metrics.normal_approval_interruptions += 1;
90
+ else throw error;
91
+ }
92
+
93
+ if (index < DELTA_ATTACKS) {
94
+ try {
95
+ await task.run({
96
+ service: 'demo',
97
+ action: 'item.update',
98
+ context: { catalog, item: `unrelated:${index}` }
99
+ }, async () => {
100
+ metrics.provider_effects += 1;
101
+ metrics.unauthorized_effects += 1;
102
+ return { updated: `unrelated:${index}` };
103
+ });
104
+ } catch (error) {
105
+ if (error instanceof AuthorityApprovalRequiredError && error.code === 'authority_delta_required') {
106
+ metrics.delta_step_ups += 1;
107
+ } else {
108
+ throw error;
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ const percent = (numerator, denominator) => denominator === 0 ? 0 : (numerator / denominator) * 100;
115
+ const report = {
116
+ ...metrics,
117
+ normal_task_completion_rate: percent(metrics.completed_normal_tasks, metrics.normal_tasks),
118
+ false_approval_rate: percent(metrics.normal_approval_interruptions, metrics.normal_tasks),
119
+ delta_step_up_rate: percent(metrics.delta_step_ups, metrics.delta_attacks),
120
+ unauthorized_effect_rate: percent(metrics.unauthorized_effects, metrics.delta_attacks)
121
+ };
122
+
123
+ console.log(JSON.stringify(report, null, 2));
124
+
125
+ if (report.normal_task_completion_rate !== 100) throw new Error('normal task completion regressed');
126
+ if (report.false_approval_rate !== 0) throw new Error('normal tasks were interrupted by approval');
127
+ if (report.delta_step_up_rate !== 100) throw new Error('authority deltas were not consistently surfaced');
128
+ if (report.unauthorized_effect_rate !== 0) throw new Error('an unrelated effect executed');
129
+
130
+ console.log('PASS -> deterministic product utility benchmark preserved useful task completion and blocked unrelated effects');