@byok-sdk/cloud 0.18.0 → 0.20.0

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.
@@ -1,4 +1,4 @@
1
- import { type AuthenticatedDeviceAssertion, type Clock, type DeviceAssertionExpectedBinding, type DeviceAssertionReplayAuthority } from '@byok-sdk/core';
1
+ import { type AuthenticatedDeviceAssertion, type AuthenticatedTaskAssertion, type Clock, type DeviceAssertionExpectedBinding, type DeviceAssertionReplayAuthority } from '@byok-sdk/core';
2
2
  import type { CloudCrypto } from '../crypto/port';
3
3
  import type { DeviceDirectory } from '../stores/ports';
4
4
  export interface HostedDeviceAssertionAuthDeps {
@@ -16,3 +16,43 @@ export interface HostedDeviceAssertionAuthDeps {
16
16
  * host-owned and are never represented by this short-lived credential.
17
17
  */
18
18
  export declare function authenticateHostedDeviceAssertion(input: unknown, deps: HostedDeviceAssertionAuthDeps): Promise<AuthenticatedDeviceAssertion | undefined>;
19
+ /**
20
+ * The task lane needs exactly the same hosted authorities as the device lane —
21
+ * the same directory rows, the same verifier, the same replay ledger, the same
22
+ * clock and the same expected binding. An alias rather than a second interface,
23
+ * because two structurally identical declarations are two places for the
24
+ * hosted composition's requirements to drift apart.
25
+ */
26
+ export type HostedTaskAssertionAuthDeps = HostedDeviceAssertionAuthDeps;
27
+ /**
28
+ * Hosted composition for the task-scoped tool-authority exchange
29
+ * (`byok-task-assertion-v1`, contract §8.1 / §8.2(2)).
30
+ *
31
+ * Everything §8.2(2) puts on this side is here or in the core function it
32
+ * composes: strict parse, the CURRENT device row (exists, not revoked, legal
33
+ * key), signature, exact issuer/product/audience, valid time window, the TTL
34
+ * ceiling, and one atomic `jti` consumption under the task lane's own `schema`
35
+ * segment — so the same `jti` presented as a device assertion and as a task
36
+ * assertion occupies two key slots and neither lane can burn the other's. The
37
+ * replay segment is chosen inside core from the envelope kind; this function
38
+ * deliberately has no say in it, because a caller able to name the segment
39
+ * would be a caller able to spend the other lane's key.
40
+ *
41
+ * A DEVICE envelope presented here authenticates as `undefined`, always: §8.1
42
+ * gives the task lane zero acceptance and zero fallback, and that is a property
43
+ * of core's parser (`parseTaskAssertionEnvelope`), not a branch anyone here
44
+ * could relax.
45
+ *
46
+ * A replay store that cannot answer REJECTS the promise rather than resolving
47
+ * to a principal — §8.2(2)'s "an unavailable replay store fails, it does not
48
+ * downgrade authentication". A host turns that into an availability error; it
49
+ * must never turn it into signature-only acceptance.
50
+ *
51
+ * What this deliberately does NOT do is the frozen-offer check — that the
52
+ * task, AgentRef and toolset in the claims belong to THIS Execution, and that
53
+ * the Execution still permits a new tool call. That authority is the host's
54
+ * (§8.2(3)), and a parameter for it here would be an invitation to synthesize
55
+ * it. This function's answer is "these claims are authentic and spent once",
56
+ * never "this invocation is admitted".
57
+ */
58
+ export declare function authenticateHostedTaskAssertion(input: unknown, deps: HostedTaskAssertionAuthDeps): Promise<AuthenticatedTaskAssertion | undefined>;
@@ -63,6 +63,42 @@ export declare const CLOUD_CAPABILITIES: {
63
63
  readonly skillPacks: 'skills.pack';
64
64
  /** Optional, one-way redacted Agent-memory snapshot mutation route. */
65
65
  readonly agentMemoryProjection: 'agent.memory.projection';
66
+ /**
67
+ * Remote authenticated runtime input preparation (C07 G4): the host control
68
+ * plane enqueues `agent.input.preparation` and the device discharges it
69
+ * through the completion/status pair.
70
+ *
71
+ * Informational like `host-mcp-task-context`, not route-gating. Both routes
72
+ * mount unconditionally (`cloud.ts`) because the completion route is the
73
+ * DEVICE's only way to discharge a mailbox row this same deployment handed
74
+ * it — withholding it would strand the device's redelivery cursor rather
75
+ * than degrade a feature. For the same reason the completion route asserts
76
+ * no DEVICE capability either: the device-level `agent-input-preparation-v5`
77
+ * flag gates ADMISSION (`enqueueInputPreparation`) and nothing else, so an
78
+ * unconfigured device is refused a row instead of being handed one whose
79
+ * only honest answer — `input_preparation_unconfigured` — it could not then
80
+ * record. What declaring THIS capability promises is that this deployment's
81
+ * host side actually drives the lane, which is what a Host reads before
82
+ * calling `enqueueInputPreparation` instead of probing.
83
+ */
84
+ readonly inputPreparation: 'agent.input.preparation';
85
+ /**
86
+ * Contract §8.1's capability gate for task-scoped tool authority
87
+ * (`byok-task-assertion-v1`), deployment-level channel.
88
+ *
89
+ * The SAME literal name `@byok-sdk/protocol`'s
90
+ * `HOST_MCP_TASK_CONTEXT_CAPABILITY` carries on the device-level channel —
91
+ * §8.1 requires both to be in place, and a name spelled differently in the
92
+ * two would make "both" unverifiable.
93
+ *
94
+ * Unlike its siblings above this capability mounts no route in this package:
95
+ * what a deployment promises by declaring it is that its host side actually
96
+ * VERIFIES task assertions (`authenticateHostedTaskAssertion` plus the frozen
97
+ * offer check that only the host can make). That is why it is default-off
98
+ * below and not derivable from anything this package can inspect — §8.2(1):
99
+ * the capability is declared only once it is completely implemented.
100
+ */
101
+ readonly hostMcpTaskContext: 'host-mcp-task-context';
66
102
  };
67
103
  export type CloudCapability = (typeof CLOUD_CAPABILITIES)[keyof typeof CLOUD_CAPABILITIES];
68
104
  /** The wire DTO for `GET /byok/capabilities` — core's shape, bound to a cloud-owned route. */
@@ -91,6 +127,13 @@ export interface FullCapabilityDeclarationOptions {
91
127
  * mutation route.
92
128
  */
93
129
  readonly includeAgentMemoryProjection?: boolean;
130
+ /**
131
+ * Contract §8.2(1): the task lane is declared only by a deployment whose host
132
+ * side verifies task assertions end to end. There is nothing this package can
133
+ * probe to decide that for an embedder, and guessing would declare a gate the
134
+ * deployment does not hold — so it is off unless a composition says otherwise.
135
+ */
136
+ readonly includeHostMcpTaskContext?: boolean;
94
137
  }
95
138
  /** Every capability the standard composition can serve, plus explicitly wired composition-bound ones. */
96
139
  export declare function fullCapabilityDeclaration(version?: number, options?: FullCapabilityDeclarationOptions): CapabilityDeclaration;
package/dist/cloud.d.ts CHANGED
@@ -19,12 +19,13 @@ import { type RecurringExecutionInput } from './recurring';
19
19
  import { type BoardItem, type BoardItemInput, type BoardListQuery, type BoardPage, type CapabilityDeclaration, type Clock, type CoreStores, type PresenceHint, type SkillPackStore, type TenantId, type TenantReadiness } from '@byok-sdk/core';
20
20
  import type { ActivityTail } from './activity';
21
21
  import type { ApprovalTimelineTail } from './approval-timeline';
22
- import { type Envelope, type TaskOfferType, type AgentRef, type AgentContentReadPayload, type AgentMessageDispositionPayload, type AgentMessagePublishPayload, type AgentMessageServerContext, type AgentHomeProjectionCompletionRequest, type AgentHomeProjectionPayload, type AgentHomeProjectionReadback, type AgentMemoryProjectionEraseResult, type TaskOfferPayload, type TaskSteerPayload, type TaskOfferForAgentPayload, type TaskOfferForAgentWithEgressPayload, type TaskOfferForAgentWithEgressFreshPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
22
+ import { type Envelope, type TaskOfferType, type AgentRef, type AgentContentReadPayload, type AgentMessageDispositionPayload, type AgentMessagePublishPayload, type AgentMessageServerContext, type AgentHomeProjectionCompletionRequest, type AgentHomeProjectionPayload, type AgentHomeProjectionReadback, type AgentInputPreparationPayload, type InputPreparationCompletionRequest, type InputPreparationReadback, type AgentMemoryProjectionEraseResult, type TaskOfferPayload, type TaskSteerPayload, type TaskOfferForAgentPayload, type TaskOfferPreparedPayload, type TaskOfferForAgentWithEgressPayload, type TaskOfferForAgentWithEgressFreshPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
23
23
  import type { TokenSigner } from './auth/tokens';
24
24
  import type { CloudCrypto } from './crypto/port';
25
25
  import { type RouteDescriptor } from './router/registry';
26
26
  import { type ByokCloudObserver } from './inbound';
27
27
  import { type AgentHomeProjectionReceiptInput } from './agent-home-projections';
28
+ import { type InputPreparationReceiptInput } from './input-preparations';
28
29
  import type { AgentMemoryProjectionAuthorizer, AgentMemoryProjectionStore } from './agent-memory-projection';
29
30
  import type { BlobContentProxy, CloudStores, DeviceRecord, AgentEgressRecord, PairingCodeInfo, RequestReceipt, TaskAttempt, TaskAttemptListQuery, TaskAttemptPage } from './stores/ports';
30
31
  import { type DeviceTerminal, type TerminalResult } from './terminal-result';
@@ -155,6 +156,22 @@ export interface AgentDispatchInput {
155
156
  /** Strict Agent payload carrying the exact opaque AgentRef. */
156
157
  readonly payload: TaskOfferForAgentPayload;
157
158
  }
159
+ /**
160
+ * Strict dispatch of an already-counted preparation back to the device that
161
+ * counted it.
162
+ *
163
+ * Deliberately NOT an optional field on {@link AgentDispatchInput}: the wire
164
+ * message is distinct for the freeze-rule reason documented on
165
+ * `TaskOfferPreparedPayloadSchema`, and a host API that could express both
166
+ * through one input would let a caller reach the ordinary lane by omitting one
167
+ * property.
168
+ */
169
+ export interface PreparedDispatchInput {
170
+ /** Supply one to make the enqueue addressable by the host's own id; otherwise cloud mints one. */
171
+ readonly taskId?: string;
172
+ /** Instruction-free strict payload naming the preparation this Execution consumes. */
173
+ readonly payload: TaskOfferPreparedPayload;
174
+ }
158
175
  /** Strict Agent dispatch that supplies the policy consumed by the typed egress lanes. */
159
176
  export interface AgentEgressDispatchInput {
160
177
  /** Supply one to make the enqueue addressable by the host's own id; otherwise cloud mints one. */
@@ -180,6 +197,10 @@ export interface AgentContentReadInput {
180
197
  export type AgentHomeProjectionInput = AgentHomeProjectionPayload;
181
198
  /** Exact request identity a host must echo to read back durable projection status. */
182
199
  export type AgentHomeProjectionStatusInput = AgentHomeProjectionReceiptInput;
200
+ /** Task-free exact-device remote preparation request, intentionally unrelated to TaskAttempt. */
201
+ export type InputPreparationInput = AgentInputPreparationPayload;
202
+ /** Exact request identity a host must echo to read back durable preparation status. */
203
+ export type InputPreparationStatusInput = InputPreparationReceiptInput;
183
204
  /** Optional targeting for {@link ByokCloud.approveTask}. */
184
205
  export interface ApproveTaskOptions {
185
206
  /**
@@ -201,6 +222,9 @@ export interface EnqueuedAgentControl {
201
222
  export interface EnqueuedAgentHomeProjection extends EnqueuedAgentControl {
202
223
  readonly status: AgentHomeProjectionReadback;
203
224
  }
225
+ export interface EnqueuedInputPreparation extends EnqueuedAgentControl {
226
+ readonly status: InputPreparationReadback;
227
+ }
204
228
  /** Immutable executable offer authority, independent of mailbox retention. */
205
229
  export type TaskOfferReadback = {
206
230
  [T in TaskOfferType]: {
@@ -255,6 +279,17 @@ export interface ByokCloud {
255
279
  * before either the mailbox append or task-attempt open.
256
280
  */
257
281
  enqueueAgentOffer(tenant: TenantId, deviceId: string, input: AgentDispatchInput): Promise<EnqueuedOffer>;
282
+ /**
283
+ * Host control plane: enqueue an offer for an already-counted preparation.
284
+ *
285
+ * Admission requires the device to durably advertise both the Agent-home
286
+ * contract and `agent-input-preparation-v5` — the second because only a device
287
+ * that can prepare holds the durable record this offer names. A device that
288
+ * advertises neither never receives the message, and a device whose protocol
289
+ * build predates the type skips it whole rather than running it as an
290
+ * ordinary instruction offer.
291
+ */
292
+ enqueuePreparedOffer(tenant: TenantId, deviceId: string, input: PreparedDispatchInput): Promise<EnqueuedOffer>;
258
293
  /**
259
294
  * Host control plane: enqueue the typed egress-policy Agent offer. Missing
260
295
  * egress/reliable-ack capabilities reject before a mailbox row is allocated.
@@ -276,6 +311,17 @@ export interface ByokCloud {
276
311
  getAgentHomeProjectionStatus(tenant: TenantId, deviceId: string, input: AgentHomeProjectionStatusInput): Promise<AgentHomeProjectionReadback | undefined>;
277
312
  /** Direct device completion endpoint authority; first exact terminal receipt wins. */
278
313
  completeAgentHomeProjection(tenant: TenantId, deviceId: string, receipt: AgentHomeProjectionCompletionRequest): Promise<AgentHomeProjectionReadback>;
314
+ /**
315
+ * Durable, task-free remote input preparation for precisely one admitted
316
+ * device. Capability admission, the immutable desired receipt and the
317
+ * mailbox append happen in that order, so a refused call leaves NO receipt
318
+ * and NO delivery row behind.
319
+ */
320
+ enqueueInputPreparation(tenant: TenantId, deviceId: string, input: InputPreparationInput): Promise<EnqueuedInputPreparation>;
321
+ /** Tenant/device/request-bound durable desired-state and terminal-outcome readback. */
322
+ getInputPreparationStatus(tenant: TenantId, deviceId: string, input: InputPreparationStatusInput): Promise<InputPreparationReadback | undefined>;
323
+ /** Direct device completion endpoint authority; first exact terminal receipt wins. */
324
+ completeInputPreparation(tenant: TenantId, deviceId: string, receipt: InputPreparationCompletionRequest): Promise<InputPreparationReadback>;
279
325
  /**
280
326
  * Server-side consent revocation and hosted projection erasure. It does not
281
327
  * depend on a device being online and never imports anything back locally.
package/dist/errors.d.ts CHANGED
@@ -72,6 +72,16 @@ export declare const CLOUD_ERROR_CODES: {
72
72
  readonly agent_home_projection_receipt_mismatch: 'agent_home_projection_receipt_mismatch';
73
73
  /** A receipt-store row at the projection namespace violated the frozen projection schema. */
74
74
  readonly agent_home_projection_receipt_invalid: 'agent_home_projection_receipt_invalid';
75
+ /** A remote input-preparation request id already names a different immutable desired request. */
76
+ readonly input_preparation_request_conflict: 'input_preparation_request_conflict';
77
+ /** A device completion did not identify a stored desired request for this exact device. */
78
+ readonly input_preparation_request_not_found: 'input_preparation_request_not_found';
79
+ /** A device completion changed the first durable terminal outcome. */
80
+ readonly input_preparation_completion_conflict: 'input_preparation_completion_conflict';
81
+ /** A completion did not exactly echo its immutable desired request/Agent/policy binding. */
82
+ readonly input_preparation_receipt_mismatch: 'input_preparation_receipt_mismatch';
83
+ /** A receipt-store row at the preparation namespace violated the frozen schema. */
84
+ readonly input_preparation_receipt_invalid: 'input_preparation_receipt_invalid';
75
85
  /** A hosted Agent-memory mutation did not match the durable task/device/AgentRef binding. */
76
86
  readonly agent_memory_projection_task_mismatch: 'agent_memory_projection_task_mismatch';
77
87
  /** The embedder-owned grant/consent authority denied a hosted memory mutation. */
@@ -0,0 +1,17 @@
1
+ /** Device-authenticated completion and readback for remote input preparations. */
2
+ import type { Context } from 'hono';
3
+ import { type InputPreparationCompletionRequest, type InputPreparationReadback } from '@byok-sdk/protocol';
4
+ import { type DeviceRouteDeps } from './shared';
5
+ import type { TenantStores } from '../tenant-stores';
6
+ export interface InputPreparationRouteDeps extends DeviceRouteDeps {
7
+ readonly complete: (stores: TenantStores, deviceId: string, receipt: InputPreparationCompletionRequest) => Promise<InputPreparationReadback>;
8
+ readonly status: (stores: TenantStores, deviceId: string, input: {
9
+ readonly requestId: string;
10
+ readonly agentRef: {
11
+ readonly agentId: string;
12
+ readonly profileRevision: string;
13
+ };
14
+ }) => Promise<InputPreparationReadback | undefined>;
15
+ }
16
+ export declare function inputPreparationCompletionHandler(deps: InputPreparationRouteDeps): (c: Context) => Promise<Response>;
17
+ export declare function inputPreparationStatusHandler(deps: InputPreparationRouteDeps): (c: Context) => Promise<Response>;
package/dist/index.d.ts CHANGED
@@ -16,9 +16,11 @@ export { isTenantId, tenantId } from '@byok-sdk/core';
16
16
  export type { TenantId } from '@byok-sdk/core';
17
17
  export { createByokCloud } from './cloud';
18
18
  export type { TaskAgentMessage } from './task-agent-message';
19
- export type { ByokCloud, ByokCloudOptions, AgentDispatchInput, AgentEgressDispatchInput, AgentEgressFreshSessionDispatchInput, AgentContentReadInput, AgentHomeProjectionInput, AgentHomeProjectionStatusInput, ApproveTaskOptions, EnqueueOfferInput, EnqueueToolsetOfferInput, RejectTaskOptions, EnqueuedAgentControl, EnqueuedAgentHomeProjection, EnqueuedOffer, TaskOfferReadback, } from './cloud';
19
+ export type { ByokCloud, ByokCloudOptions, AgentDispatchInput, AgentEgressDispatchInput, AgentEgressFreshSessionDispatchInput, AgentContentReadInput, AgentHomeProjectionInput, AgentHomeProjectionStatusInput, InputPreparationInput, InputPreparationStatusInput, ApproveTaskOptions, EnqueueOfferInput, EnqueueToolsetOfferInput, RejectTaskOptions, EnqueuedAgentControl, EnqueuedAgentHomeProjection, EnqueuedInputPreparation, EnqueuedOffer, TaskOfferReadback, } from './cloud';
20
20
  export { agentHomeProjectionCompletionKey, agentHomeProjectionRequestKey, readAgentHomeProjectionStatus, recordAgentHomeProjectionCompletion, } from './agent-home-projections';
21
21
  export type { AgentHomeProjectionReceiptInput } from './agent-home-projections';
22
+ export { inputPreparationCompletionKey, inputPreparationRequestKey, readInputPreparationStatus, recordInputPreparationCompletion, sameInputPreparationRequest, } from './input-preparations';
23
+ export type { InputPreparationReceiptInput } from './input-preparations';
22
24
  export { AGENT_HOME_CONTRACT_CAPABILITY, DEFAULT_EVENTS_PAGE_LIMIT, DEFAULT_LONG_POLL_HOLD_MS, DEFAULT_LONG_POLL_INTERVAL_MS, DEFAULT_MAX_BLOB_SIZE_BYTES, } from './cloud';
23
25
  export { DEFAULT_BOARD_PAGE_LIMIT, DEFAULT_BOARD_STREAM_HEARTBEAT_INTERVAL_MS, DEFAULT_BOARD_STREAM_QUERY_INTERVAL_MS, DEFAULT_BOARD_STREAM_RECONCILIATION_INTERVAL_MS, } from './handlers/board';
24
26
  export { DEFAULT_SKILL_PACK_PAGE_LIMIT } from './handlers/skill-packs';
@@ -39,8 +41,8 @@ export { authenticateBearer, extractBearerToken } from './auth/bearer';
39
41
  export type { BearerAuthDeps } from './auth/bearer';
40
42
  export { DEFAULT_DEVICE_PROOF_CLOCK_SKEW_MS, DEFAULT_DEVICE_PROOF_MAX_LIFETIME_MS, MAX_DEVICE_PROOF_CLOCK_SKEW_MS, MAX_DEVICE_PROOF_MAX_LIFETIME_MS, authenticateDeviceProof, } from './auth/device-proof';
41
43
  export type { AuthenticatedDeviceProof, DeviceProofAuthDeps, DeviceProofRequestBinding, } from './auth/device-proof';
42
- export { authenticateHostedDeviceAssertion } from './auth/device-assertion';
43
- export type { HostedDeviceAssertionAuthDeps } from './auth/device-assertion';
44
+ export { authenticateHostedDeviceAssertion, authenticateHostedTaskAssertion } from './auth/device-assertion';
45
+ export type { HostedDeviceAssertionAuthDeps, HostedTaskAssertionAuthDeps } from './auth/device-assertion';
44
46
  export { DEVICE_IDENTITY_PROOF_KEY_EPOCH, DEVICE_IDENTITY_PROOF_KEY_ID, PAIRING_CODE_TTL_MS, createAuthPlane, } from './auth/plane';
45
47
  export type { AuthPlane, AuthPlaneDeps, MintedAccessToken, PairInput } from './auth/plane';
46
48
  export { createWebCrypto } from './crypto/web-crypto';