@arnilo/prism 0.0.12 → 0.0.13
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 +11 -0
- package/dist/agents.js +21 -2
- package/dist/contracts.d.ts +25 -1
- package/dist/extensions.d.ts +11 -0
- package/dist/extensions.js +15 -0
- package/dist/identity.d.ts +92 -0
- package/dist/identity.js +257 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +3 -1
- package/dist/persistence-lifecycle.d.ts +103 -0
- package/dist/persistence-lifecycle.js +204 -0
- package/dist/providers/openai-compatible.d.ts +5 -1
- package/dist/providers/openai-compatible.js +15 -6
- package/dist/secure-agent.js +7 -1
- package/dist/testing/persistence-schema.d.ts +2 -2
- package/dist/testing/persistence-schema.js +35 -2
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +6 -0
- package/docs/a2a.md +2 -0
- package/docs/agent-identity.md +111 -0
- package/docs/credential-storage.md +3 -0
- package/docs/database-persistence.md +18 -7
- package/docs/extensions.md +1 -0
- package/docs/guardrails.md +3 -0
- package/docs/host-security.md +5 -1
- package/docs/index.md +17 -8
- package/docs/mcp-tools.md +2 -0
- package/docs/migration.md +27 -0
- package/docs/model-routing.md +102 -0
- package/docs/observability.md +2 -0
- package/docs/performance.md +19 -0
- package/docs/policy-and-audit.md +127 -0
- package/docs/postgres-persistence.md +1 -1
- package/docs/provider-packages.md +8 -1
- package/docs/provider-request-policies.md +2 -0
- package/docs/providers/azure.md +74 -0
- package/docs/providers/bedrock.md +72 -0
- package/docs/providers/google.md +1 -0
- package/docs/providers/openai-compatible.md +3 -1
- package/docs/providers/openrouter.md +2 -0
- package/docs/providers/vertex.md +71 -0
- package/docs/public-contracts.md +3 -1
- package/docs/release-and-install.md +78 -6
- package/docs/review-coverage-2026-07-23-phase-8.md +245 -0
- package/docs/runs-and-usage.md +2 -0
- package/docs/server.md +33 -4
- package/docs/sqlite-persistence.md +1 -1
- package/docs/supervisors.md +2 -0
- package/docs/work-connectors.md +28 -0
- package/docs/work-tools.md +114 -0
- package/package.json +4 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Review coverage — 2026-07-23 Phase 8
|
|
2
|
+
|
|
3
|
+
Working evidence for Plan 076 Task 0. Freezes Phase 8 / Release **0.0.13** scope, package names, primitive ownership, finite limits, external revisions, threats, tests, docs, and release gates before implementation.
|
|
4
|
+
|
|
5
|
+
**Evidence frozen:** 2026-07-23. **Prism source:** `5b21f78cde6c4f3c9e7760f153c4bd8670d104e4`. **Release target:** 0.0.13. **Default test rule:** network-free fakes, CLI fake executables, and protocol fixtures; cloud/provider/tenant live canaries remain explicit host/operator gates.
|
|
6
|
+
|
|
7
|
+
## Status legend
|
|
8
|
+
|
|
9
|
+
| Status | Meaning |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `existing` | Current public contract covers the requirement. |
|
|
12
|
+
| `extend` | Owning task adds a generic reusable contract to an existing seam. |
|
|
13
|
+
| `new-package` | New optional workspace package; core stays free of product/cloud/CLI SDKs. |
|
|
14
|
+
| `compose` | Existing public primitives suffice; package-local wiring only. |
|
|
15
|
+
| `out-of-scope` | Later phase or deliberately unsupported; must not land in 0.0.13. |
|
|
16
|
+
|
|
17
|
+
## Frozen product decision
|
|
18
|
+
|
|
19
|
+
0.0.13 closes **enterprise identity, policy/audit, model governance, enterprise-cloud providers, server deployment seams, persistence lifecycle hooks, and least-privilege Microsoft 365 / Google Workspace connectors** only.
|
|
20
|
+
|
|
21
|
+
**Not in 0.0.13** (do not implement here):
|
|
22
|
+
|
|
23
|
+
| Deferred or rejected item | Owner / reason |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| Conversation storage/service, artifact co-work review API, personal memory consent UX, channel/device adapters | 0.0.14+ product scope. |
|
|
26
|
+
| Studio, hosted cloud, managed observability, visual workflow editor, broad Slack/Teams chat catalog | Demand-gated 0.1.x control-plane / product layer. |
|
|
27
|
+
| Local Office `.docx`/`.xlsx`/`.pptx` executable, SDK, wrapper, protocol, or runtime package | Product boundary; hosts may use external skills/tools. |
|
|
28
|
+
| User authentication database or identity provider inside Prism | Host/application owns auth; Prism accepts host-verified identity only. |
|
|
29
|
+
| Mandatory global policy engine, KMS, WORM store, queue broker, or container orchestrator | Host-replaceable seams; at most one reference adapter per seam. |
|
|
30
|
+
| Model-controlled M365/GWS command strings, generic Graph/Discovery requests, CLI login, tenant-admin commands, debug/telemetry dumps, credential-store access | Injection / over-privilege / secret-leakage risk. |
|
|
31
|
+
| Advertising Teams/Planner/To Do or Docs/Sheets/Slides as universal parity | Capability-gated only; Outlook/Gmail/calendar/files/tasks are the 0.0.13 common denominator. |
|
|
32
|
+
| Folding Azure/Bedrock/Vertex into consumer Anthropic/Google packages | Enterprise workload-identity and region/private-endpoint semantics differ. |
|
|
33
|
+
| Redis/SQS/other queue adapters by default | **Task 5 deferred:** no measured Postgres polling bottleneck recorded; keep coordinator poll path. |
|
|
34
|
+
| Putting work connectors or enterprise-cloud SDKs into `@arnilo/prism-code` / `@arnilo/prism-sdk` | Profiles stay lean; enroll only in `@arnilo/prism-all` unless size/adoption review revises this freeze. |
|
|
35
|
+
|
|
36
|
+
## Frozen external revisions
|
|
37
|
+
|
|
38
|
+
| Surface | Frozen reference | Compatibility decision |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| Prism | [`5b21f78cde6c4f3c9e7760f153c4bd8670d104e4`](../plans/076-release-0-0-13-enterprise-identity-policy-governance-work-connectors.md) | Existing ownership/credential/permission/provider/server/persistence/lease seams inventoried below. |
|
|
41
|
+
| Node.js | Release support remains Node 20+ | Optional packages use Web `Request`/`Response`, `execFile`, abort, and existing bounded patterns; no framework dependency. |
|
|
42
|
+
| Microsoft Entra Agent ID | [Governing Agent Identities](https://learn.microsoft.com/en-us/entra/id-governance/agent-id-governance-overview); [What are agent identities?](https://learn.microsoft.com/en-us/entra/agent-id/what-are-agent-identities) | Informs `Principal`/`AgentIdentity` sponsor/owner/delegation/scope/expiry vocabulary. Prism does **not** embed Entra; hosts verify tokens/claims and supply identity context. |
|
|
43
|
+
| CLI for Microsoft 365 | [CLI for Microsoft 365 docs](https://pnp.github.io/cli-microsoft365/); npm `@pnp/cli-microsoft365`; GitHub `pnp/cli-microsoft365` | Host-installed execution adapter only. Prism ships hard-coded typed `execFile` argument templates; never `m365 login`, setup, tenant-admin, or model-built argv. |
|
|
44
|
+
| Google Workspace CLI | [googleworkspace/cli](https://github.com/googleworkspace/cli); npm `@googleworkspace/cli` (`gws`) | Host-installed execution adapter only. Discovery-dynamic surface is **not** exposed to models; Prism allow-lists typed operations, forces JSON/NDJSON parse bounds, disables interactive auth/debug from Prism. |
|
|
45
|
+
| Azure OpenAI / Foundry Entra auth | [Entra ID authentication for Azure OpenAI / Foundry Models](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/managed-identity) | Host supplies late-bound workload credential callback (Managed Identity / token provider). No static keys in fixtures. |
|
|
46
|
+
| Azure private network | [Configure virtual networks for Foundry Tools](https://learn.microsoft.com/en-us/azure/ai-services/cognitive-services-virtual-networks) | Preserve custom subdomain / private-endpoint / VNet semantics on package config; do not rewrite endpoints. |
|
|
47
|
+
| Amazon Bedrock IAM | [Identity and access management for Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html) | Host supplies AWS credential callback (IRSA / instance role / assumed role). Package never embeds long-lived keys. |
|
|
48
|
+
| Amazon Bedrock PrivateLink | [Interface VPC endpoints for Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/vpc-interface-endpoints.html) | Preserve region + optional VPC endpoint override; fail closed if residency policy rejects region. |
|
|
49
|
+
| Google Vertex / ADC | [Authenticate to Vertex AI (generative)](https://cloud.google.com/vertex-ai/generative-ai/docs/start/authenticate); [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials) | Host supplies ADC/workload credential callback. Separate from `@arnilo/prism-provider-google` consumer API-key package. |
|
|
50
|
+
| OpenRouter routing metadata | Existing `openRouterRouting` compat fields; [OpenRouter provider docs](providers/openrouter.md) | Router may honor metadata only when policy/allow-list/residency permit; never bypass governance. |
|
|
51
|
+
|
|
52
|
+
## Frozen package and API contract
|
|
53
|
+
|
|
54
|
+
| Decision | Frozen choice |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| Core identity | Add `Principal`, `AgentIdentity`, `IdentityVerifier`, `assertIdentityActive`, `narrowIdentity` (names may alias but semantics frozen). Extend `OwnershipScope`; no identity database in core. |
|
|
57
|
+
| Policy package | New optional `@arnilo/prism-policy` with evaluator + decision ledger + cursor export; redacted/evidence-ref payloads only. |
|
|
58
|
+
| Model router | New optional `@arnilo/prism-model-router` as `ProviderResolver`-compatible facade over allow-list/residency/budget/rate/circuit/fallback. |
|
|
59
|
+
| Enterprise cloud providers | New optional `@arnilo/prism-provider-azure`, `@arnilo/prism-provider-bedrock`, `@arnilo/prism-provider-vertex`. Keep `@arnilo/prism-provider-anthropic` and `@arnilo/prism-provider-google` separate. |
|
|
60
|
+
| Work connectors | New optional `@arnilo/prism-work-tools` with subpaths `./microsoft365` and `./google-workspace` only. |
|
|
61
|
+
| Server | Extend `@arnilo/prism-server` with optional health/readiness, host auth/rate-limit adapter hooks, graceful drain, event replay helpers, and worker/coordinator deployment contracts over existing leases. |
|
|
62
|
+
| Persistence lifecycle | Extend existing `RetentionPolicy` / production persistence seams with apply/delete/legal-hold/export hooks, optional host KMS/envelope callback, tenant quotas, and extension allow-list/signature policy. |
|
|
63
|
+
| Idempotency | Add a narrow generic side-effect `IdempotencyStore` (or equivalent) consumed by both connector subpaths; reuse session `idempotencyKey` patterns for inspiration, not as the connector store. |
|
|
64
|
+
| Profile manifests | New packages enroll in `@arnilo/prism-all` only. `@arnilo/prism-code` and `@arnilo/prism-sdk` stay free of work connectors and enterprise-cloud SDKs. |
|
|
65
|
+
| Release graph | Task 10 versions the graph to **0.0.13** and adds six publishable packages (**35 → 41** manifests: root + 40 under `packages/`). |
|
|
66
|
+
| Queues | Absent by default. Task 5 may add a queue adapter only with measured Postgres polling/load evidence recorded in Plan 076 Compromises/Further Actions and this page. |
|
|
67
|
+
|
|
68
|
+
### Frozen package names and subpaths
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
@arnilo/prism-policy
|
|
72
|
+
@arnilo/prism-model-router
|
|
73
|
+
@arnilo/prism-provider-azure
|
|
74
|
+
@arnilo/prism-provider-bedrock
|
|
75
|
+
@arnilo/prism-provider-vertex
|
|
76
|
+
@arnilo/prism-work-tools
|
|
77
|
+
@arnilo/prism-work-tools/microsoft365
|
|
78
|
+
@arnilo/prism-work-tools/google-workspace
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Capability traceability matrix
|
|
82
|
+
|
|
83
|
+
| Phase 8 roadmap criterion | Existing surface | Minimum gap | Status / owner | Required proof | Docs | Release gate |
|
|
84
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
85
|
+
| Authenticated `Principal` / `AgentIdentity` with tenant, sponsor/owner, delegated actor, scopes, credential refs, issued/expiry, revocation; immutable propagation | `OwnershipScope`, server `authorize`→ownership, run/tool/workflow ownership fields, OTel attributes | Core identity types + verifier seam + propagation asserts | `extend` / Task 1 | expired/revoked/wrong-tenant/widen-scope denial; MCP/A2A/server/tool/workflow/telemetry carry refs without secrets | `agent-identity.md`, host-security, public-contracts | offline core + package tests |
|
|
86
|
+
| Policy-decision ledger allow/deny/modify/approval + WORM export without unrestricted payloads | `GuardrailDecision`, `PermissionPolicy`, tool_approval interruption, run feedback immutability, redaction | Optional policy package + redacted store/export | `new-package` / Task 2 | attribution, version mismatch fail-closed, export pagination, payload rejection | `policy-and-audit.md` | offline package test |
|
|
87
|
+
| Model governance allow-list/residency/routing/fallback/circuit/retry/budget/rate + diagnostics | `ProviderResolver`, `ProviderRequestPolicy`, OpenRouter routing metadata, run budgets | Optional model-router facade + diagnostics | `new-package` / Task 3 | deny-before-call matrix; diagnostic redaction; OpenRouter gated by policy | `model-routing.md`, openrouter | offline package test |
|
|
88
|
+
| Azure / Bedrock / Vertex enterprise adapters with workload identity + region/private-endpoint | Provider package conformance, `CredentialResolver`, OpenAI-compatible patterns where applicable | Three provider packages + host credential callbacks | `new-package` / Task 4 | MI/IRSA/ADC mocks; region preserved; consumer Anthropic/Google unchanged | `providers/azure.md`, `bedrock.md`, `vertex.md` | offline + gated live canaries |
|
|
89
|
+
| Server health/readiness, auth/rate-limit adapters, drain, replay, worker/coordinator | `createPrismHandler`, authorize/ownership, leases/fencing, SSE/resume, `queryEvents` | Optional health/drain/replay/deployment helpers | `extend` / Task 5 | multi-process failover/drain/replay; unauthorized detail denial; queues absent by default | `server.md`, performance | offline multi-process fixtures |
|
|
90
|
+
| M365 + GWS identity-scoped tools (mail/calendar/files/tasks); Teams/Planner/To Do and Docs/Sheets/Slides capability-gated | `ToolDefinition`, tool approval, web-tools subpath pattern, coding-security `execFile` bounds | `@arnilo/prism-work-tools` subpaths + typed templates | `new-package` / Task 7 (M365), Task 8 (GWS) | fake CLI argv injection/schema/JSON bounds; capability mismatch; least scopes | `work-tools.md`, `work-connectors.md` | offline package test + gated tenant canaries |
|
|
91
|
+
| Draft-then-approve mutations; idempotent retries via operation/draft/resource IDs + concurrency tokens | tool_approval interruption, session `idempotencyKey`, checkpoints | Connector draft store + side-effect idempotency store | `extend` + `new-package` / Task 7, Task 8 | duplicate retry no-op; stale ETag fail; send only after approval | work-tools docs | offline fixtures |
|
|
92
|
+
| Hard-coded CLI `execFile` templates only; no model command/login/admin/debug/credential access | coding-security sandbox `execFile`, credential redaction | Package-local template registry + isolated config dirs | `compose` / Task 7, Task 8 | forbidden argv/env denial; credentials never in argv/model context | work-connectors, credential-storage, host-security | offline hostile argv tests |
|
|
93
|
+
| Retention/deletion/legal-hold/export, optional KMS/envelope, extension allow-list/signature, tenant quotas | `RetentionPolicy`, feedback delete, credentials-node envelope crypto, extension kernel trust | Persistence lifecycle + extension signature/allow-list + quota hooks | `extend` / Task 6 | hold blocks delete; unsigned extension deny; quota contention; key rotation mock | database-persistence, host-security, extensions | offline store + extension tests |
|
|
94
|
+
| Bounded performance for identity/policy/router/connectors/deployment | Existing server/web-tools/persistence limits | Frozen caps below + benchmarks | `compose` / Tasks 1–8, 10 | hostile overflow; network-free benchmarks | performance, review page | `sdk:ready` + benchmark |
|
|
95
|
+
| Narrow optional contracts; no mandatory control plane | Product boundaries; profile packaging | Package/profile guards | `compose` / Tasks 0, 9–10 | pack graph 41; prism-code/sdk free of connectors/cloud SDKs | release-and-install, migration | pack/install + diff review |
|
|
96
|
+
| Security fail-closed: verified identity, narrow delegation, late-bound creds, least privilege, approvals, share/attachment/residency policy | host-security checklist, redaction, permission/trust | Threat matrix enforcement in owning tasks | `compose` / all tasks | negative tests per threat row | host-security + task docs | security review before publish |
|
|
97
|
+
|
|
98
|
+
## Primitive and caller inventory
|
|
99
|
+
|
|
100
|
+
| Primitive / symbol | Existing contract and callers | Phase 8 disposition |
|
|
101
|
+
| --- | --- | --- |
|
|
102
|
+
| `OwnershipScope` (`tenantId`/`accountId`/`userId`) | Persistence records, tools, agents, server authorize result, workflows, leases | **Extend** with authenticated identity context that still projects to ownership; never replace ownership checks. |
|
|
103
|
+
| `CredentialResolver` / OAuth store / credentials-node envelope | Late-bound secrets; encrypted vault/keychain | Reuse. Enterprise cloud + connectors resolve via host callbacks; secrets never in CLI argv or model context. |
|
|
104
|
+
| `PermissionPolicy` / `TrustPolicy` | Tool/extension/resource checks | Reuse at connector and extension boundaries; optional policy package may record decisions. |
|
|
105
|
+
| `ProviderRequestPolicy` / `ProviderResolver` | Provider request mutation and model→provider resolution | Reuse. Model-router wraps resolver; request policies remain chainable. |
|
|
106
|
+
| Guardrails + `tool_approval` interruption | `createSecureAgent`, agent loop durable suspend | Reuse for connector mutation approvals; do not invent a second approval runtime. |
|
|
107
|
+
| Run ledger / feedback / `AgentEventRecord` | Durable redacted run evidence | Reuse for attributable diagnostics refs; policy ledger stays separate schema. |
|
|
108
|
+
| Checkpoints / leases | Durable interruption and multi-process fencing | Reuse for drain/worker/coordinator and connector draft durability where applicable. |
|
|
109
|
+
| `RetentionPolicy` (+ query on production stores) | Stored policy rows; limited apply semantics today | **Extend** with apply/delete/legal-hold/export/quota hooks. |
|
|
110
|
+
| Server `authorize` → ownership | `@arnilo/prism-server` every route | **Extend** optional health/rate-limit/drain/replay; ownership still only from authorize. |
|
|
111
|
+
| OTel / observability package | Span/metric export | Propagate identity refs as redacted attributes; no secret material. |
|
|
112
|
+
| Supervisor / A2A / MCP | Delegation and remote tool bridges | Accept verified identity; refuse cross-tenant widening. |
|
|
113
|
+
| coding-security `execFile` / sandbox bounds | Sandbox FS/shell | Pattern reuse for CLI adapters (typed args, caps, kill); not a coding-workspace dependency for work-tools. |
|
|
114
|
+
| web-tools subpath packaging | `@arnilo/prism-web-tools/{brave,exa,firecrawl}` | Copy packaging pattern for work-tools subpaths. |
|
|
115
|
+
| Session `idempotencyKey` | Session append dedup | Inspiration only; connectors need a side-effect idempotency store keyed by identity+operation. |
|
|
116
|
+
|
|
117
|
+
### Primitive decision
|
|
118
|
+
|
|
119
|
+
**Authorized generic core extensions (each needs ≥2 consumers):**
|
|
120
|
+
|
|
121
|
+
1. Authenticated identity contracts + attach/assert/narrow helpers (consumers: server, tools, workflows, MCP, A2A, telemetry, connectors, providers/router).
|
|
122
|
+
2. Side-effect `IdempotencyStore` contract (consumers: M365 + GWS; optional future connectors).
|
|
123
|
+
3. Retention/legal-hold/export/quota persistence hooks (consumers: sqlite + postgres production stores; memory may unsupported/explicit).
|
|
124
|
+
4. Extension allow-list / signature policy seam on the extension kernel (consumers: host loaders + contribution discovery).
|
|
125
|
+
|
|
126
|
+
**Authorized new packages:** `@arnilo/prism-policy`, `@arnilo/prism-model-router`, `@arnilo/prism-provider-azure`, `@arnilo/prism-provider-bedrock`, `@arnilo/prism-provider-vertex`, `@arnilo/prism-work-tools` (`./microsoft365`, `./google-workspace`).
|
|
127
|
+
|
|
128
|
+
**Authorized package/server extensions:** health/drain/replay/deployment helpers on `@arnilo/prism-server`; optional KMS/envelope callback wiring via credentials-node patterns without forcing cloud KMS SDKs into core.
|
|
129
|
+
|
|
130
|
+
**Rejected:** auth DB; control plane; Office packages; model-controlled CLI; merging enterprise cloud into consumer Anthropic/Google; mandatory queues; putting connectors/cloud SDKs into `prism-code`/`prism-sdk`; protocol/UI frameworks in core.
|
|
131
|
+
|
|
132
|
+
## Frozen finite limits and charging points
|
|
133
|
+
|
|
134
|
+
**Rule:** validate every untrusted field before persistence, provider call, CLI spawn, or export enqueue. Owning tasks may tighten defaults but must not raise hard caps without updating this page, tests, and docs.
|
|
135
|
+
|
|
136
|
+
### Identity / policy
|
|
137
|
+
|
|
138
|
+
| Resource | Default / hard cap | Charge/check point | Failure/cleanup owner |
|
|
139
|
+
| --- | ---: | --- | --- |
|
|
140
|
+
| Scopes per identity | 64 / 256 | Before verify/narrow/attach | Task 1 rejects. |
|
|
141
|
+
| One scope string | 128 B / 512 B | Before verify/narrow | Task 1 rejects. |
|
|
142
|
+
| Identity metadata map | 4 KiB / 16 KiB | Before persistence/telemetry attach | Task 1 omits/rejects; never stores secrets. |
|
|
143
|
+
| Credential reference string | 256 B / 2 KiB | Before attach | Task 1 rejects; never expands to secret. |
|
|
144
|
+
| Policy decision record | 8 KiB / 64 KiB | Before ledger append | Task 2 rejects unrestricted payloads. |
|
|
145
|
+
| Evidence ref / reason | 1 KiB / 8 KiB each | Before append/export | Task 2 truncates with marker or rejects. |
|
|
146
|
+
| Policy export page | 100 / 500 | Before export cursor read | Task 2 pages; no full scan. |
|
|
147
|
+
| Identity/policy CPU path | sync O(fields); 0 network in core helpers | Before tool/provider work | Tasks 1–2 fail closed locally. |
|
|
148
|
+
|
|
149
|
+
### Model router
|
|
150
|
+
|
|
151
|
+
| Resource | Default / hard cap | Charge/check point | Failure/cleanup owner |
|
|
152
|
+
| --- | ---: | --- | --- |
|
|
153
|
+
| Resolve attempts (including fallbacks) | 3 / 8 | Before each provider resolve | Task 3 stops; emits attributable deny. |
|
|
154
|
+
| Concurrent circuit keys retained | 1,024 / 16,384 | Before circuit state insert | Task 3 evicts oldest or rejects new key. |
|
|
155
|
+
| Diagnostics record | 8 KiB / 64 KiB | Before audit/telemetry | Task 3 redacts; no secrets/raw prompts. |
|
|
156
|
+
| Token/cost budget fields | finite non-negative; host units | Before provider call | Task 3 denies when exhausted. |
|
|
157
|
+
| Rate-limit window memory | per identity+model key; capped with circuit keys | Before admit | Task 3 denies with retry hint bounded. |
|
|
158
|
+
|
|
159
|
+
### Work connectors (per tool invocation)
|
|
160
|
+
|
|
161
|
+
| Resource | Default / hard cap | Charge/check point | Failure/cleanup owner |
|
|
162
|
+
| --- | ---: | --- | --- |
|
|
163
|
+
| Pagination pages | 20 / 100 | Before next-page CLI/API call | Task 7 / Task 8 stop with partial+cursor or error. |
|
|
164
|
+
| Items per page / aggregate items | 50 / 500; 200 / 2,000 | Before parse/accumulate | Task 7 / Task 8 reject/truncate with marker. |
|
|
165
|
+
| Request/response body | 256 KiB / 2 MiB | Before spawn/parse | Task 7 / Task 8 kill/reject. |
|
|
166
|
+
| Attachment / file bytes | 5 MiB / 25 MiB; 10 MiB / 50 MiB | Before upload/download/scan | Task 7 / Task 8 deny; scan hook required for inbound. |
|
|
167
|
+
| CLI stdout/stderr capture | 2 MiB / 16 MiB | While reading pipes | Task 7 / Task 8 abort process. |
|
|
168
|
+
| Process wall time | 60 s / 10 min | Spawn abort signal | Task 7 / Task 8 kill process tree best-effort. |
|
|
169
|
+
| Concurrent CLI processes / identity | 2 / 8 | Before spawn | Task 7 / Task 8 queue-reject. |
|
|
170
|
+
| Retries for idempotent ops | 2 / 4 | Before retry | Task 7 / Task 8 require idempotency key. |
|
|
171
|
+
| Rate / cost counters | finite host ceilings | Before mutation | Task 7 / Task 8 deny. |
|
|
172
|
+
| Operation/draft/idempotency key | 256 B / 2 KiB | Before store write | Task 7 / Task 8 reject. |
|
|
173
|
+
|
|
174
|
+
### Server deployment / persistence lifecycle
|
|
175
|
+
|
|
176
|
+
| Resource | Default / hard cap | Charge/check point | Failure/cleanup owner |
|
|
177
|
+
| --- | ---: | --- | --- |
|
|
178
|
+
| Health/readiness response | 4 KiB / 64 KiB; no tenant payloads by default | Before serialize | Task 5 redacts. |
|
|
179
|
+
| Drain admit cutoff | 30 s / 5 min | After drain flag | Task 5 rejects new admits; in-flight use existing timeouts. |
|
|
180
|
+
| Replay page rows / cursor | 100 / 500; 4 KiB / 16 KiB | Before `queryEvents` | Task 5 pages; authorize+ownership required. |
|
|
181
|
+
| Publish/capacity concurrent runs | reuse server 16 / 256 | Existing handler | Task 5 documents; does not raise hard caps. |
|
|
182
|
+
| Tenant quota counters | finite host ceilings per resource class | Before persist/spawn | Task 6 denies with attributable reason. |
|
|
183
|
+
| Envelope/KMS payload | reuse credentials-node envelope file caps (4 MiB / 16 MiB) | Before encrypt/decrypt | Task 6 rejects; host KMS timeout bounded (60 s hard). |
|
|
184
|
+
|
|
185
|
+
**Forbidden:** unbounded CLI output, model-built argv, credential-in-argv, unrestricted policy payload store, uncapped router fallback loops, raising hard caps silently, default queue broker, Office binary packaging.
|
|
186
|
+
|
|
187
|
+
## Work-connector capability freeze
|
|
188
|
+
|
|
189
|
+
| Workload | 0.0.13 status | Notes |
|
|
190
|
+
| --- | --- | --- |
|
|
191
|
+
| Outlook / Gmail search, read, draft, approved send | supported common denominator | Draft durable before send; external-recipient policy fail closed. |
|
|
192
|
+
| Calendar list/create/update | supported common denominator | Idempotent create/update with provider concurrency tokens. |
|
|
193
|
+
| OneDrive/SharePoint / Drive files search/read/upload/move/share | supported common denominator | Share external targets policy-gated; attachment caps apply. |
|
|
194
|
+
| Tasks list/create/complete | supported common denominator | Provider-specific task systems mapped to shared result shapes where possible. |
|
|
195
|
+
| Teams / Planner / To Do | capability-gated optional | Not advertised as universal parity; absent capability → explicit unsupported. |
|
|
196
|
+
| Docs / Sheets / Slides cloud ops | capability-gated optional | Same; no local Office execution implied. |
|
|
197
|
+
| CLI login / setup / tenant-admin / debug / credential export | unsupported from Prism | Host may run outside Prism; tools must deny if invoked. |
|
|
198
|
+
| Generic Graph or Discovery passthrough | unsupported | Hard-coded templates only. |
|
|
199
|
+
|
|
200
|
+
## Threat and authority matrix
|
|
201
|
+
|
|
202
|
+
| Boundary | Trusted authority | Untrusted input | Mandatory control | Default / unsupported |
|
|
203
|
+
| --- | --- | --- | --- | --- |
|
|
204
|
+
| Identity claims | Host `IdentityVerifier` | Caller headers/body identity fields | Verify before attach; expiry/revocation/tenant checks | Caller-asserted identity unsupported. |
|
|
205
|
+
| Delegation | Parent verified identity | Requested child scopes | `child.scopes ⊆ parent.scopes`; tenant immutable | Scope widening / tenant swap unsupported. |
|
|
206
|
+
| Credentials | Host resolver / workload callback / CLI config dir | Model text, tool args, env dumps | Late-bound resolve; never argv/model/context; per-identity isolated config | Credential discovery from model unsupported. |
|
|
207
|
+
| Policy decisions | Host policy + ledger | Action/resource context | Redact; store evidence refs; version pin | Unrestricted prompt/tool body in ledger unsupported. |
|
|
208
|
+
| Model routing | Allow-list + residency + budgets | Model id, OpenRouter metadata | Deny before provider call on miss/exhaustion | Bypass router via metadata unsupported when policy attached. |
|
|
209
|
+
| Cloud providers | Host workload identity | Endpoint/region overrides | Preserve private-endpoint/region; mock-only offline | Static keys in repo/fixtures unsupported. |
|
|
210
|
+
| Server health/replay | Authorize + ownership | Health query detail flags, replay cursors | Minimal health by default; ownership-scoped replay | Anonymous tenant dump unsupported. |
|
|
211
|
+
| Connector CLI | Hard-coded templates + host binary pin | Model-suggested command/args | `execFile` argv from template only; version/schema validate at start | Model command, login, admin, debug unsupported. |
|
|
212
|
+
| Mutations | Durable draft + tool_approval + idempotency store | Retry storms, stale ETags | Draft→approve→send; concurrency token; dedupe | Blind send/share/delete unsupported. |
|
|
213
|
+
| Attachments / shares | Host scan + recipient policy | Files, external recipients | Cap bytes; scan hook; external deny-by-default | Unscanned inbound / open external share unsupported. |
|
|
214
|
+
| Extensions | Allow-list + signature policy | Unsigned packages | Fail closed when policy enabled | Unsigned load when enterprise policy on unsupported. |
|
|
215
|
+
| Retention / legal hold | Host hold + retention policy | Delete requests | Hold blocks delete/export rules per policy | Silent purge under hold unsupported. |
|
|
216
|
+
|
|
217
|
+
## Validation matrix for Task 0
|
|
218
|
+
|
|
219
|
+
| Check | Frozen assertion |
|
|
220
|
+
| --- | --- |
|
|
221
|
+
| Traceability | Every Phase 8 roadmap Functional/Performance/Code Quality/Security criterion has one primary Task 1–10 owner; 0.0.14 conversations/artifacts/channels/devices and 0.1.x Studio/control-plane have none. |
|
|
222
|
+
| Package names | Exact names/subpaths listed above; 35 → 41 manifests at release; new packages only in `prism-all`. |
|
|
223
|
+
| Primitive reuse | Only identity, side-effect idempotency, retention/hold/export/quota, and extension signature/allow-list are authorized generic core/extension gaps; each needs ≥2 consumers. |
|
|
224
|
+
| CLI boundary | M365/GWS adapters are hard-coded templates via `execFile`; no model-controlled command surface. |
|
|
225
|
+
| Cloud separation | Azure/Bedrock/Vertex packages distinct from consumer Anthropic/Google. |
|
|
226
|
+
| Finite resources | All identity/policy/router/connector/deployment caps above are enforced by owning tasks. |
|
|
227
|
+
| Security | Host-verified identity, narrow delegation, late-bound credentials, draft-then-approve, fail-closed residency/share/attachment/extension/hold policy. |
|
|
228
|
+
| Queues | **Deferred after Task 5:** no Redis/SQS adapter. Postgres/`createWorkflowCoordinator` checkpoint polling remains default; revisit only with measured polling/load evidence. |
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
## Documentation and release ownership
|
|
232
|
+
|
|
233
|
+
- Task 0: this evidence page, `docs/index.md`, and `docs.test.ts` regression guard.
|
|
234
|
+
- Task 1: identity contracts + propagation docs (`agent-identity.md` and cross-links).
|
|
235
|
+
- Task 2: `@arnilo/prism-policy` + `policy-and-audit.md`.
|
|
236
|
+
- Task 3: `@arnilo/prism-model-router` + `model-routing.md`.
|
|
237
|
+
- Task 4: azure/bedrock/vertex provider packages + provider docs.
|
|
238
|
+
- Task 5: server deployment seams + `server.md` / performance notes.
|
|
239
|
+
- Task 6: retention/KMS/quotas/extension signature docs + persistence/security pages.
|
|
240
|
+
- Task 7: `@arnilo/prism-work-tools/microsoft365` + shared work-tools contracts.
|
|
241
|
+
- Task 8: `@arnilo/prism-work-tools/google-workspace` + shared result-shape parity docs.
|
|
242
|
+
- Task 9: canonical docs, examples, migration, index navigation.
|
|
243
|
+
- Task 10: 0.0.13 graph, benchmarks, pack/install, supply-chain, dry-run publish, roadmap completion evidence.
|
|
244
|
+
|
|
245
|
+
No public implementation API changes land in Task 0. This page, `roadmap.md` Phase 8, and Plan 076 are authoritative until implementation; later tasks may tighten defaults but cannot widen scope, raise hard caps, add Office packages, embed an auth DB/control plane, expose model-controlled CLI, merge enterprise cloud into consumer Anthropic/Google, or enable default queues without updating this evidence, tests, docs, and plan.
|
package/docs/runs-and-usage.md
CHANGED
|
@@ -286,6 +286,7 @@ console.log(cacheUsageReport(aggregate?.usage));
|
|
|
286
286
|
- **Idempotency is host-owned.** The runtime writes the key into `RunRecord.idempotencyKey`; enforcing unique keys and deduplicating retries is the host adapter's responsibility.
|
|
287
287
|
- **Tenant isolation.** `OwnershipScope` fields are copied from the active ownership scope, but the runtime does not enforce tenant isolation for ledger rows. Feedback is stricter: append/query/delete require tenant plus account/user, and first-party stores compare the exact scope to the linked run.
|
|
288
288
|
- **Feedback privacy.** Comments/tags/metadata can contain PII. Configure a feedback redactor, apply retention, and call owned `delete()` for erasure. Never copy comments or tag values into metric labels.
|
|
289
|
+
- **Policy audit is separate.** Enterprise allow/deny/modify/approval rows with evidence refs live in optional `@arnilo/prism-policy`, not `RunLedger`. See [Policy and audit](policy-and-audit.md).
|
|
289
290
|
|
|
290
291
|
## Optional batching and durability
|
|
291
292
|
|
|
@@ -304,6 +305,7 @@ Runtime session snapshots cache one leaf/generation for at most one second. Succ
|
|
|
304
305
|
|
|
305
306
|
## Related APIs
|
|
306
307
|
|
|
308
|
+
- [Policy and audit](policy-and-audit.md): optional enterprise decision ledger (separate from run usage rows).
|
|
307
309
|
- [Performance limits](performance.md): batching, cursor keys, and production sizing assumptions.
|
|
308
310
|
- [Agent/session runtime](agent-session-runtime.md): `session.run()` and runtime event emission.
|
|
309
311
|
- [Agent events](agent-events.md): `AgentEvent` union and `session.subscribe()`.
|
package/docs/server.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-server` exposes explicitly selected agents and workflows through one framework-free `(Request) => Promise<Response>` handler. It supports direct agent results, bounded agent/workflow SSE, opt-in durable agent status/resume, durable workflow start/enqueue/status/cancel/resume/replay, ownership-scoped schedules, host authorization, ownership propagation, redaction, and
|
|
5
|
+
`@arnilo/prism-server` exposes explicitly selected agents and workflows through one framework-free `(Request) => Promise<Response>` handler. It supports direct agent results, bounded agent/workflow SSE, opt-in durable agent status/resume, durable workflow start/enqueue/status/cancel/resume/replay, ownership-scoped schedules, host authorization, ownership propagation, redaction, resource ceilings, and optional deployment seams (health/readiness, drain, host rate-limit adapter, ownership-scoped event replay, worker/coordinator lease election).
|
|
6
6
|
|
|
7
|
-
No listener starts on import. Empty `agents`/`workflows` maps expose nothing. Authentication, authorization, route selection, durable stores, TLS, rate limiting, and framework/serverless adaptation remain host-owned.
|
|
7
|
+
No listener starts on import. Empty `agents`/`workflows` maps expose nothing. Authentication, authorization, route selection, durable stores, TLS, distributed rate limiting, queues, and framework/serverless adaptation remain host-owned.
|
|
8
8
|
|
|
9
9
|
## When to use it
|
|
10
10
|
|
|
@@ -15,6 +15,7 @@ Use `AgentSession` or workflow APIs directly for in-process applications. Do not
|
|
|
15
15
|
## Inputs / request
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
|
+
const drain = createPrismDrainController({ deadlineMs: 30_000 });
|
|
18
19
|
const handler = createPrismHandler({
|
|
19
20
|
agents?: Record<string, Agent | PrismAgentExposure>,
|
|
20
21
|
agentRuns?: Record<string, PrismAgentRunExposure>, // explicit durable status/resume only
|
|
@@ -22,8 +23,11 @@ const handler = createPrismHandler({
|
|
|
22
23
|
schedules?: WorkflowSchedules | ((authorization, signal) => WorkflowSchedules),
|
|
23
24
|
authorize: async ({ request, operation, capabilityId }) => false | {
|
|
24
25
|
ownership: { tenantId?: string; accountId?: string; userId?: string },
|
|
26
|
+
identity?: AgentIdentity, // optional host-verified; must match ownership
|
|
25
27
|
metadata?: Record<string, unknown>,
|
|
26
28
|
},
|
|
29
|
+
drain?, // blocks admit ops with 503 while draining
|
|
30
|
+
rateLimit?, // host adapter after authorize, before session/run create
|
|
27
31
|
basePath?: "/prism",
|
|
28
32
|
allowedHosts?: string[],
|
|
29
33
|
allowedOrigins?: string[],
|
|
@@ -31,6 +35,7 @@ const handler = createPrismHandler({
|
|
|
31
35
|
limits?: PrismServerLimits,
|
|
32
36
|
disconnectAborts?: boolean,
|
|
33
37
|
});
|
|
38
|
+
const health = createPrismHealthHandler({ ready: () => store.ping(), drain });
|
|
34
39
|
```
|
|
35
40
|
|
|
36
41
|
At least one non-empty ownership field must come from `authorize()`. Request JSON never chooses ownership.
|
|
@@ -117,14 +122,36 @@ Default/hard ceilings:
|
|
|
117
122
|
| concurrent runs | 16 | 256 |
|
|
118
123
|
| subscriber queue | 128 | 4,096 |
|
|
119
124
|
| request/run timeout | 120 s | 30 min |
|
|
125
|
+
| health response | 4 KiB | 64 KiB |
|
|
126
|
+
| drain admit cutoff | 30 s | 5 min |
|
|
127
|
+
| replay page / cursor | 100 / 4 KiB | 500 / 16 KiB |
|
|
128
|
+
|
|
129
|
+
## Deployment seams (optional)
|
|
130
|
+
|
|
131
|
+
Compose beside `createPrismHandler` — Prism starts no listener, container orchestrator, or queue worker.
|
|
132
|
+
|
|
133
|
+
| Helper | Role |
|
|
134
|
+
| --- | --- |
|
|
135
|
+
| `createPrismHealthHandler` | `GET /health`, `/livez`, `/readyz`. Minimal JSON; `?detail=1` requires `authorizeDetail`. No secrets/tenant payloads by default. Ready fails while draining. |
|
|
136
|
+
| `createPrismDrainController` | `beginDrain()` rejects admit ops (`agent.run`/`stream`/`resume`, workflow run/stream/enqueue/resume/replay, schedule create/trigger) with `503 ERR_PRISM_SERVER_DRAINING`. Status/cancel/list stay open. |
|
|
137
|
+
| `rateLimit` on handler | Host adapter after authorize, before session create. Return denial `{ retryAfterMs, code, message }` → `429` + optional `Retry-After`. `createMemoryRateLimiter` is single-process only. |
|
|
138
|
+
| `createPrismEventReplay` / `createPrismReplayHandler` | Ownership-scoped `queryEvents` pages (`redacted: true`). Does not re-run work. Unauthorized replay denies. |
|
|
139
|
+
| `createPrismDeploymentLease` | Lease election under `prism.server.deployment`. Coordinator replica holds `key: "coordinator"` before schedule ticks; workers run `@arnilo/prism-workflows` `createWorkflowCoordinator` for queued runs (fencing tokens). |
|
|
140
|
+
|
|
141
|
+
**Queues:** Redis/SQS/other adapters are absent. Postgres checkpoint polling via `createWorkflowCoordinator` remains the default background path until a measured polling/load justification is recorded.
|
|
142
|
+
|
|
143
|
+
Network-free demo: [`examples/server-deployment-seams.ts`](../examples/server-deployment-seams.ts).
|
|
120
144
|
|
|
121
145
|
## Security and performance notes
|
|
122
146
|
|
|
123
147
|
- `authorize()` is required and runs for every matched operation before capability lookup or body execution. Return `false` on missing/invalid credentials. Do not trust caller ownership fields.
|
|
148
|
+
- Optional `authorization.identity` must be host-verified (`AgentIdentity.verified`); the handler asserts activity and ownership match, then forwards identity into agent runs. Caller-asserted identity without a host verifier is rejected.
|
|
124
149
|
- Use authorization metadata only for non-secret audit context. Never put credentials in metadata, input, route IDs, run IDs, checkpoints, events, or responses.
|
|
125
150
|
- Configure `SecretRedactor` before runs. Redaction matches known secrets; it is not DLP.
|
|
126
151
|
- Agent tools and workflow tool nodes still need their own `PermissionPolicy`, `ToolValidator`, and `ExecutionPolicy`. HTTP authorization does not replace side-effect policy.
|
|
127
|
-
- Host and origin allow-lists are exact string matches. Configure reverse-proxy normalization, TLS,
|
|
152
|
+
- Host and origin allow-lists are exact string matches. Configure reverse-proxy normalization, TLS, IP policy, CSRF/cookie policy, and authentication outside Prism. Optional `rateLimit` is an attributable short-circuit only — not a WAF.
|
|
153
|
+
- Health endpoints reveal process/liveness only by default; detail flags require host authorize and must omit secrets/tenant dumps.
|
|
154
|
+
- Drain and event replay require the same ownership/authorize boundary as other routes; replay never invokes providers or tools.
|
|
128
155
|
- SSE uses bounded upstream subscriber queues. Consumer cancellation aborts owned work by default and releases concurrency; set `disconnectAborts: false` only when the host deliberately owns background completion.
|
|
129
156
|
- Source inputs/resource URLs remain host responsibilities and use existing resource/media SSRF policies. Server package does not fetch URLs.
|
|
130
157
|
- Schedule routes never accept ownership from JSON. Services carry mandatory ownership and explicit workflow/calculator registries; route authorization cannot broaden either. Replay applies workflow ownership/hash/approval checks.
|
|
@@ -134,8 +161,10 @@ A2A routes are not added to `createPrismHandler()`. Install `@arnilo/prism-super
|
|
|
134
161
|
|
|
135
162
|
## Related APIs
|
|
136
163
|
|
|
164
|
+
- [Agent identity](agent-identity.md): optional verified identity on authorize results.
|
|
165
|
+
- [Performance](performance.md): capacity notes for concurrent runs and deployment probes.
|
|
137
166
|
- [Agent/session runtime](agent-session-runtime.md): direct result and event stream semantics.
|
|
138
|
-
- [Workflows](workflows.md): durable checkpoints, status, cancellation,
|
|
167
|
+
- [Workflows](workflows.md): durable checkpoints, status, cancellation, exact-once resume, and `createWorkflowCoordinator` workers.
|
|
139
168
|
- [MCP client and server exposure](mcp-tools.md): selected MCP capabilities and web-standard MCP transport.
|
|
140
169
|
- [Host security guide](host-security.md): remote-boundary checklist.
|
|
141
170
|
- [A2A interoperability](a2a.md): separately mounted A2A 1.0 handler/client.
|
|
@@ -99,7 +99,7 @@ For resume/timeline flows, use `queryRuns`, `queryEvents`, `queryToolCalls`, and
|
|
|
99
99
|
- The package is optional and workspace-local; `@arnilo/prism` core has no SQLite dependency.
|
|
100
100
|
- Hosts choose the database path and own backup, retention enforcement, and filesystem permissions.
|
|
101
101
|
- `SessionAppendOptions` idempotency rows are durable in `prism_session_append_idempotency` and survive reopen.
|
|
102
|
-
- Schema version **
|
|
102
|
+
- Schema version **5** applies `001_init`, `002_usage_scope`, `003_run_feedback`, `004_session_search`, and `005_lifecycle_hold_quota`. Migration 003 adds immutable `prism_run_feedback` rows with run FK/cascade deletion and owner/run/trace cursor indexes. Migration 004 adds session search FTS (FTS5 virtual table `prism_session_search_fts` dual-written on append) plus `prism_sessions(updated_at, id)` cursor index; existing entries are backfilled once. `persistence.feedback` validates exact run ownership, bounds/redacts through optional `feedbackRedactor`, queries bounded pages, and deletes only exact-owned IDs. Search hits never include credentials; ownership filters apply when present. PostgreSQL shares the same model with dialect-local DDL.
|
|
103
103
|
- Pass an existing `better-sqlite3` `Database` via `database` when your host already manages connections.
|
|
104
104
|
|
|
105
105
|
## Security and performance notes
|
package/docs/supervisors.md
CHANGED
|
@@ -61,10 +61,12 @@ Child factories resolve their own providers/credentials and construct context/me
|
|
|
61
61
|
- Tool budget is checked before side effects. Token usage is enforced on terminal aggregate usage and can exceed by at most one provider turn because providers report tokens after generation.
|
|
62
62
|
- Abort and timeout cover hooks, child creation, nested delegation, and the run. Host child code must cooperate with `AbortSignal`.
|
|
63
63
|
- Redaction applies before hook input, run metadata/results, completion hooks, and events. Child credentials are never supplied in delegation context.
|
|
64
|
+
- When forwarding verified identity into children or A2A, use `narrowIdentity` / `assertIdentityPropagation` so scopes and tenant cannot widen across the boundary.
|
|
64
65
|
- Static workflows remain smaller and more reproducible for known graphs.
|
|
65
66
|
|
|
66
67
|
## Related APIs
|
|
67
68
|
|
|
69
|
+
- [Agent identity](agent-identity.md): host-verified identity and narrow delegation.
|
|
68
70
|
- [A2A interoperability](a2a.md): separate remote protocol boundary. `A2ATaskLifecycle` adapts host durable agent/workflow state directly; it does not route A2A execution through local supervisor child planning.
|
|
69
71
|
- [Workflows](workflows.md): preferred deterministic orchestration.
|
|
70
72
|
- [Working and semantic memory](working-and-semantic-memory.md): child scope construction.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Work connectors
|
|
2
|
+
|
|
3
|
+
Least-privilege Microsoft 365 and Google Workspace connectors live in `@arnilo/prism-work-tools`.
|
|
4
|
+
|
|
5
|
+
## Principles
|
|
6
|
+
|
|
7
|
+
1. **Host-pinned binary** — Prism never downloads or shells an untrusted CLI path.
|
|
8
|
+
2. **Hard-coded argv templates** — models choose typed tool args; they never supply command strings.
|
|
9
|
+
3. **Draft-then-approve** — mutations create a draft; side effects run only after host approval.
|
|
10
|
+
4. **Idempotent retries** — `IdempotencyStore` keyed by identity + operation key.
|
|
11
|
+
5. **Isolated config** — per-identity `configDir` (CLI `HOME`); no credential argv.
|
|
12
|
+
6. **Shared result shapes** — mail/calendar/file/task list/get tools normalize onto `WorkMailMessage` / `WorkCalendarEvent` / `WorkFileItem` / `WorkTaskItem` without hiding provider-specific ops.
|
|
13
|
+
|
|
14
|
+
## Microsoft 365
|
|
15
|
+
|
|
16
|
+
See [Work tools](work-tools.md). Adapter: `createMicrosoft365CliAdapter` / subpath `@arnilo/prism-work-tools/microsoft365`.
|
|
17
|
+
|
|
18
|
+
Uses [@pnp/cli-microsoft365](https://pnp.github.io/cli-microsoft365/) commands such as `outlook message list|get`, `outlook mail send`, `outlook event list|add`, `file list|add`, `spo file sharinglink add`. To Do / Planner / Teams remain capability-gated.
|
|
19
|
+
|
|
20
|
+
## Google Workspace
|
|
21
|
+
|
|
22
|
+
See [Work tools](work-tools.md). Adapter: `createGoogleWorkspaceCliAdapter` / subpath `@arnilo/prism-work-tools/google-workspace`.
|
|
23
|
+
|
|
24
|
+
Uses [`@googleworkspace/cli` (`gws`)](https://github.com/googleworkspace/cli): `gmail users messages list|get`, `gmail +send`, `calendar events list|insert`, `drive files list|create`, `drive permissions create`, `tasks tasks *`. Docs/Sheets/Slides create remain capability-gated. Discovery `schema` and `auth`/`login`/`setup` are forbidden from Prism argv.
|
|
25
|
+
|
|
26
|
+
## Out of scope
|
|
27
|
+
|
|
28
|
+
Local Office binaries, model-controlled CLI, generic Graph/Discovery free-form calls, tenant-admin/login/debug from Prism.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Work tools
|
|
2
|
+
|
|
3
|
+
Optional `@arnilo/prism-work-tools` package: identity-scoped Microsoft 365 and Google Workspace connectors. Host-pinned CLI binaries only; hard-coded `execFile` argv templates; draft-then-approve mutations; side-effect idempotency; shared mail/calendar/file/task result shapes.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Use when agents must read or mutate tenant mail/calendar/files/tasks through the enterprise CLI the host already operates — not through model-built shell strings or generic Graph/Discovery free-form calls.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @arnilo/prism-work-tools
|
|
13
|
+
# host separately:
|
|
14
|
+
# npm i -g @pnp/cli-microsoft365
|
|
15
|
+
# npm i -g @googleworkspace/cli
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## API
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import {
|
|
22
|
+
createWorkTools,
|
|
23
|
+
createMicrosoft365CliAdapter,
|
|
24
|
+
createGoogleWorkspaceCliAdapter,
|
|
25
|
+
createMemoryIdempotencyStore,
|
|
26
|
+
} from "@arnilo/prism-work-tools";
|
|
27
|
+
// or: import { createGoogleWorkspaceCliAdapter } from "@arnilo/prism-work-tools/google-workspace";
|
|
28
|
+
|
|
29
|
+
const microsoft365 = createMicrosoft365CliAdapter({
|
|
30
|
+
binary: process.env.M365_BIN!,
|
|
31
|
+
configDir: `/var/prism/m365/${tenant}/${user}`,
|
|
32
|
+
identity,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const googleWorkspace = createGoogleWorkspaceCliAdapter({
|
|
36
|
+
binary: process.env.GWS_BIN!,
|
|
37
|
+
configDir: `/var/prism/gws/${tenant}/${user}`,
|
|
38
|
+
identity,
|
|
39
|
+
// allowedOps: add docs.create / sheets.create / slides.create when gated
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const tools = createWorkTools({
|
|
43
|
+
microsoft365,
|
|
44
|
+
googleWorkspace,
|
|
45
|
+
idempotencyStore: createMemoryIdempotencyStore(),
|
|
46
|
+
approval: { isApproved: ({ draftId }) => hostHasApproved(draftId) },
|
|
47
|
+
externalRecipients: { allow: (addr) => addr.endsWith("@contoso.com") },
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
List/get tools return shared `WorkPage` / `WorkMailMessage` / `WorkCalendarEvent` / `WorkFileItem` / `WorkTaskItem` shapes (`untrusted: true`) via package normalizers — provider-specific fields are not hidden; they are mapped onto the common denominator.
|
|
52
|
+
|
|
53
|
+
### Hard-coded Microsoft 365 ops
|
|
54
|
+
|
|
55
|
+
Verified against [CLI for Microsoft 365](https://pnp.github.io/cli-microsoft365/) (2026-07-23):
|
|
56
|
+
|
|
57
|
+
| Prism op | CLI |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `mail.list` | `m365 outlook message list --output json` |
|
|
60
|
+
| `mail.get` | `m365 outlook message get --output json --id …` |
|
|
61
|
+
| `mail.send` | `m365 outlook mail send --output json --to … --subject … --bodyContents …` |
|
|
62
|
+
| `calendar.list` | `m365 outlook event list --output json` |
|
|
63
|
+
| `calendar.add` | `m365 outlook event add --output json --subject … --start … --end …` |
|
|
64
|
+
| `file.list` | `m365 file list --output json --webUrl … --folderUrl …` |
|
|
65
|
+
| `file.add` | `m365 file add --output json --folderUrl … --filePath …` |
|
|
66
|
+
| `file.share` | `m365 spo file sharinglink add` (`--scope organization` only) |
|
|
67
|
+
| `todo.*` / `planner.*` | capability-gated via `allowedOps` |
|
|
68
|
+
|
|
69
|
+
### Hard-coded Google Workspace ops
|
|
70
|
+
|
|
71
|
+
Verified against [`@googleworkspace/cli` / `gws`](https://github.com/googleworkspace/cli) (2026-07-24):
|
|
72
|
+
|
|
73
|
+
| Prism op | CLI |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `mail.list` | `gws gmail users messages list --params … --fields …` |
|
|
76
|
+
| `mail.get` | `gws gmail users messages get --params …` |
|
|
77
|
+
| `mail.send` | `gws gmail +send --to … --subject … --body …` |
|
|
78
|
+
| `calendar.list` | `gws calendar events list --params … --fields …` |
|
|
79
|
+
| `calendar.add` | `gws calendar events insert --params … --json …` |
|
|
80
|
+
| `file.list` | `gws drive files list --params … [--page-all]` (NDJSON when paginated) |
|
|
81
|
+
| `file.add` | `gws drive files create --json … --upload …` |
|
|
82
|
+
| `file.share` | `gws drive permissions create` (`type=domain\|user` only; `anyone` denied) |
|
|
83
|
+
| `task.*` | `gws tasks tasks list\|insert\|patch` |
|
|
84
|
+
| `docs.create` / `sheets.create` / `slides.create` | capability-gated via `allowedOps` |
|
|
85
|
+
|
|
86
|
+
Startup: M365 `version --output json`; GWS `--version`. Forbidden: `login`, `setup`, `auth`, `schema`, `doctor`, `--debug`, `--verbose`, credentials in argv, anonymous share, model-supplied command strings / free-form Discovery.
|
|
87
|
+
|
|
88
|
+
### Draft → approve → execute
|
|
89
|
+
|
|
90
|
+
Mutation tools (`*_mail_draft_send`, `*_draft_*`) create an in-adapter draft and return `{ status: "pending_approval", draftId }` until `approval.isApproved` is true. Retries with the same `idempotencyKey` return `{ status: "duplicate" }` after first successful execute.
|
|
91
|
+
|
|
92
|
+
## Limits
|
|
93
|
+
|
|
94
|
+
| Resource | Default / hard |
|
|
95
|
+
| --- | ---: |
|
|
96
|
+
| Pagination pages | 20 / 100 |
|
|
97
|
+
| Items / aggregate | 50/500 ; 200/2000 |
|
|
98
|
+
| Body / stdout | 256 KiB–2 MiB / 2–16 MiB |
|
|
99
|
+
| Process wall time | 60 s / 10 min |
|
|
100
|
+
| Concurrent CLI / identity | 2 / 8 |
|
|
101
|
+
|
|
102
|
+
## Security
|
|
103
|
+
|
|
104
|
+
- Require host-verified `AgentIdentity`; no cross-identity configDir reuse.
|
|
105
|
+
- External mail recipients fail closed unless `externalRecipients.allow` returns true.
|
|
106
|
+
- Anonymous / `anyone` sharing denied.
|
|
107
|
+
- CLI stdout/stderr capped; NDJSON page streams strictly parsed and page-capped; process killed on timeout/abort/overflow.
|
|
108
|
+
|
|
109
|
+
## Related
|
|
110
|
+
|
|
111
|
+
- [Work connectors](work-connectors.md)
|
|
112
|
+
- [Agent identity](agent-identity.md)
|
|
113
|
+
- [Host security](host-security.md)
|
|
114
|
+
- [Credential storage](credential-storage.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnilo/prism",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "Agent harness for AI providers, agents, sessions, and tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -119,6 +119,9 @@
|
|
|
119
119
|
"packages/server",
|
|
120
120
|
"packages/supervisor",
|
|
121
121
|
"packages/web-tools",
|
|
122
|
+
"packages/work-tools",
|
|
123
|
+
"packages/policy",
|
|
124
|
+
"packages/model-router",
|
|
122
125
|
"packages/browser",
|
|
123
126
|
"packages/ag-ui",
|
|
124
127
|
"packages/prism-*"
|