diff --git a/clients/swift/FractalClient/Sources/FractalClient/Client.swift b/clients/swift/FractalClient/Sources/FractalClient/Client.swift index 4ba33db7e92..ecfa16a4a92 100644 --- a/clients/swift/FractalClient/Sources/FractalClient/Client.swift +++ b/clients/swift/FractalClient/Sources/FractalClient/Client.swift @@ -437,7 +437,7 @@ public actor FractalClient { public func beginPairing(deviceName: String, personID: String) async throws -> Envelope { try await post("v1/client/pairings", PersonPairingBegin(apiVersion: fractalClientAPIVersion, deviceName: deviceName, personID: personID)) } public func beginPairing(_ request: PairingBegin) async throws -> Envelope { try await post("v1/client/pairings", request) } public func completePairing(pairingID: String, code: String, devicePublicKey: String) async throws -> Envelope { try await post("v1/client/pairings/\(pairingID.replacingOccurrences(of: "pairing/", with: ""))/complete", PairingComplete(apiVersion: fractalClientAPIVersion, code: code, devicePublicKey: devicePublicKey)) } - public func assistantGrant(_ id: String) async throws -> Envelope { try await get("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)") } + public func assistantGrant(_ id: String, witness: Bool = false) async throws -> Envelope { try await get("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)", query: witness ? [.init(name: "witness", value: "1")] : []) } public func assistantGrantRevoke(_ id: String) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/revoke", [String: String]()) } public func assistantGrantPolicy(_ id: String, _ policy: AssistantGrantPolicy) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/policy", policy) } public func assistantGrantReadTrust(_ id: String, _ trust: AssistantReadTrustRequest) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/read-trust", trust) } diff --git a/clients/swift/FractalClient/Sources/FractalClient/Models.swift b/clients/swift/FractalClient/Sources/FractalClient/Models.swift index 8601e40ac5b..079a3fa7c57 100644 --- a/clients/swift/FractalClient/Sources/FractalClient/Models.swift +++ b/clients/swift/FractalClient/Sources/FractalClient/Models.swift @@ -153,6 +153,8 @@ public enum ErrorCode: Codable, Sendable, Equatable { case peerTooOld case validationFailed case idempotencyConflict + case grantProfileConflict + case assistantGrantAuthorityNotReady case agentsPublicationRowTooLarge case attentionMigrated case invalidAnswer, notAnswerable @@ -245,6 +247,8 @@ public enum ErrorCode: Codable, Sendable, Equatable { case "peer-too-old": .peerTooOld case "validation-failed": .validationFailed case "idempotency-conflict": .idempotencyConflict + case "grant-profile-conflict": .grantProfileConflict + case "assistant-grant-authority-not-ready": .assistantGrantAuthorityNotReady case "stale-fence": .staleFence case "issuer-required": .issuerRequired case "pairing-origin-required": .pairingOriginRequired @@ -337,6 +341,8 @@ public enum ErrorCode: Codable, Sendable, Equatable { case .peerTooOld: "peer-too-old" case .validationFailed: "validation-failed" case .idempotencyConflict: "idempotency-conflict" + case .grantProfileConflict: "grant-profile-conflict" + case .assistantGrantAuthorityNotReady: "assistant-grant-authority-not-ready" case .staleFence: "stale-fence" case .issuerRequired: "issuer-required" case .pairingOriginRequired: "pairing-origin-required" @@ -1491,7 +1497,21 @@ public struct AssistantGrant: Codable, Sendable { public let kind, id, sessionActor, deviceID, keyID, issuer, expiresAt, consentEvidence: String; public let principal: AssistantPrincipal; public let senderClass: AssistantSenderClass; public let scopes: [AssistantScope]; public let policyRevision: UInt64; public let minimalReadMode: AssistantMinimalReadMode; public let recipientAllowlist: [String]; public let disclosureConsent, revoked: Bool /// Owner-provisioned SCG read pins; absent means every assistant read is denied. public let readTrust: AssistantReadTrust? - enum CodingKeys: String, CodingKey { case kind, id, sessionActor = "session_actor", deviceID = "device_id", keyID = "key_id", issuer, expiresAt = "expires_at", consentEvidence = "consent_evidence", principal, senderClass = "sender_class", scopes, policyRevision = "policy_revision", minimalReadMode = "minimal_read_mode", recipientAllowlist = "recipient_allowlist", disclosureConsent = "disclosure_consent", revoked, readTrust = "read_trust" } + public let conflict: GrantProfileConflictWitness? + public let clearedConflicts: [ClearedGrantProfileConflictWitness]? + enum CodingKeys: String, CodingKey { case kind, id, sessionActor = "session_actor", deviceID = "device_id", keyID = "key_id", issuer, expiresAt = "expires_at", consentEvidence = "consent_evidence", principal, senderClass = "sender_class", scopes, policyRevision = "policy_revision", minimalReadMode = "minimal_read_mode", recipientAllowlist = "recipient_allowlist", disclosureConsent = "disclosure_consent", revoked, readTrust = "read_trust", conflict, clearedConflicts = "cleared_conflicts" } +} +public enum ExternalGrantProfile: String, Codable, Sendable { case assistant, service } +public enum GrantProfileConflictCause: String, Codable, Sendable { case revoked, expired } +public struct GrantProfileWitness: Codable, Sendable { + public let grantID: String?; public let origin: String; public let profile: ExternalGrantProfile + enum CodingKeys: String, CodingKey { case grantID = "grant_id", origin, profile } +} +public struct GrantProfileConflictWitness: Codable, Sendable { + public let grants: [GrantProfileWitness] +} +public struct ClearedGrantProfileConflictWitness: Codable, Sendable { + public let grants: [GrantProfileWitness]; public let cause: GrantProfileConflictCause } public struct AssistantGrantPolicy: Codable, Sendable { public let apiVersion, consentEvidence: String; public let scopes: [AssistantScope]; public let expiresInSeconds: UInt64?; public let disclosureConsent: Bool; public let minimalReadMode: AssistantMinimalReadMode; public let recipientAllowlist: [String]? diff --git a/clients/typescript/fractal-client/Client.generated.ts b/clients/typescript/fractal-client/Client.generated.ts index 5e7eb2a1444..28a2f6808eb 100644 --- a/clients/typescript/fractal-client/Client.generated.ts +++ b/clients/typescript/fractal-client/Client.generated.ts @@ -482,8 +482,8 @@ export class FractalClient { return this.request('POST', `/v1/client/pairings/${encodeURIComponent(routedId(id))}/complete`, request, undefined, undefined, requestOptions); } - async assistantGrant(id: string): Promise> { - return this.request('GET', `/v1/client/assistant/grants/${encodeURIComponent(id)}`); + async assistantGrant(id: string, options: { witness?: boolean } = {}): Promise> { + return this.request('GET', `/v1/client/assistant/grants/${encodeURIComponent(id)}${query({ witness: options.witness ? 1 : undefined })}`); } async assistantGrantRevoke(id: string): Promise> { return this.request('POST', `/v1/client/assistant/grants/${encodeURIComponent(id)}/revoke`, {}); diff --git a/clients/typescript/fractal-client/Models.generated.ts b/clients/typescript/fractal-client/Models.generated.ts index 18856bf74b1..0ba64b5d9e7 100644 --- a/clients/typescript/fractal-client/Models.generated.ts +++ b/clients/typescript/fractal-client/Models.generated.ts @@ -793,6 +793,8 @@ export type AssistantConversationTimelineRequest = { }; export type AssistantGrant = { + cleared_conflicts?: Array; + conflict?: (GrantProfileConflictWitness | null); consent_evidence: string; device_id: Id; disclosure_consent: boolean; @@ -1237,6 +1239,11 @@ export type Capability = { version: number; }; +export type ClearedGrantProfileConflictWitness = { + cause: GrantProfileConflictCause; + grants: Array; +}; + export type ClientConnection = { actor: string; client?: string | null; @@ -1852,6 +1859,8 @@ export type ErrorCode = ( | "peer-too-old" | "validation-failed" | "idempotency-conflict" + | "grant-profile-conflict" + | "assistant-grant-authority-not-ready" | "legacy-action-receipt-untrusted" | "issuer-required" | "pairing-origin-required" @@ -1928,6 +1937,8 @@ export type ExchangeTransport = { fabric_route?: string; }; +export type ExternalGrantProfile = "assistant" | "service"; + export type FabricGrant = { detail?: string; peer?: string; @@ -1988,6 +1999,18 @@ export type GlassTab = { export type GoldenResourceSet = Array; +export type GrantProfileConflictCause = "revoked" | "expired"; + +export type GrantProfileConflictWitness = { + grants: Array; +}; + +export type GrantProfileWitness = { + grant_id: string | null; + origin: string; + profile: ExternalGrantProfile; +}; + export type HarnessAnswerInput = { positions: Array; }; diff --git a/clients/typescript/fractal-client/ReadSchema.generated.ts b/clients/typescript/fractal-client/ReadSchema.generated.ts index 7417f30ea54..1ade5c36a1f 100644 --- a/clients/typescript/fractal-client/ReadSchema.generated.ts +++ b/clients/typescript/fractal-client/ReadSchema.generated.ts @@ -1698,6 +1698,8 @@ export const ErrorCode = /*#__PURE__*/ (() => openEnum([ "peer-too-old", "validation-failed", "idempotency-conflict", + "grant-profile-conflict", + "assistant-grant-authority-not-ready", "legacy-action-receipt-untrusted", "issuer-required", "pairing-origin-required", diff --git a/clients/typescript/fractal-client/Schema.generated.ts b/clients/typescript/fractal-client/Schema.generated.ts index 780ad11cf6f..f42ab731c51 100644 --- a/clients/typescript/fractal-client/Schema.generated.ts +++ b/clients/typescript/fractal-client/Schema.generated.ts @@ -494,7 +494,41 @@ export const AssistantScope = /*#__PURE__*/ (() => Schema.Literals([ export type AssistantScope = typeof AssistantScope.Type export type AssistantScopeEncoded = typeof AssistantScope.Encoded +export const GrantProfileConflictCause = /*#__PURE__*/ (() => Schema.Literals(["revoked","expired"]).annotate({ identifier: "GrantProfileConflictCause" }))() +export type GrantProfileConflictCause = typeof GrantProfileConflictCause.Type +export type GrantProfileConflictCauseEncoded = typeof GrantProfileConflictCause.Encoded + +export const ExternalGrantProfile = /*#__PURE__*/ (() => Schema.Literals(["assistant","service"]).annotate({ identifier: "ExternalGrantProfile" }))() +export type ExternalGrantProfile = typeof ExternalGrantProfile.Type +export type ExternalGrantProfileEncoded = typeof ExternalGrantProfile.Encoded + +export const GrantProfileWitness = /*#__PURE__*/ (() => Schema.Struct({ + /** Grant ID; null only for legacy local fixtures without an ID. */ + "grant_id": Schema.OptionFromNullOr(Schema.String).annotate({ description: "Grant ID; null only for legacy local fixtures without an ID." }), + "origin": Schema.String, + "profile": ExternalGrantProfile +}).annotate({ identifier: "GrantProfileWitness" }))() +export type GrantProfileWitness = typeof GrantProfileWitness.Type +export type GrantProfileWitnessEncoded = typeof GrantProfileWitness.Encoded + +export const ClearedGrantProfileConflictWitness = /*#__PURE__*/ (() => Schema.Struct({ + "cause": GrantProfileConflictCause, + "grants": Schema.Array(GrantProfileWitness) +}).annotate({ identifier: "ClearedGrantProfileConflictWitness" }))() +export type ClearedGrantProfileConflictWitness = typeof ClearedGrantProfileConflictWitness.Type +export type ClearedGrantProfileConflictWitnessEncoded = typeof ClearedGrantProfileConflictWitness.Encoded + +export const GrantProfileConflictWitness = /*#__PURE__*/ (() => Schema.Struct({ + "grants": Schema.Array(GrantProfileWitness) +}).annotate({ identifier: "GrantProfileConflictWitness" }))() +export type GrantProfileConflictWitness = typeof GrantProfileConflictWitness.Type +export type GrantProfileConflictWitnessEncoded = typeof GrantProfileConflictWitness.Encoded + export const AssistantGrant = /*#__PURE__*/ (() => Schema.Struct({ + /** Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing. */ + "cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing." }), + /** Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses. */ + "conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, @@ -902,23 +936,25 @@ export const Envelope = /*#__PURE__*/ (() => Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "request_id": RequestId, "snapshot": Snapshot, - "value": Schema.Union([Schema.Struct({ "notes": Schema.Array(DirectiveNote), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "capabilities": Schema.Array(Capability), "event_cursor": Cursor, "grant_expires_at": optionalKey(Timestamp), "grant_id": optionalKey(Id), "grant_kind": optionalKey(Schema.Literals(["person","assistant"])), "kind": Schema.Literal("capabilities"), "limits": Schema.Struct({ "default_assistant_response_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(4096))), "max_arrangement_body_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_folders": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_key_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_name_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_operations": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_placements": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_resource_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangements": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_assistant_response_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(16384))), "max_event_items": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "max_glass_body_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glass_depth": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glass_nodes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glasses": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), /** The longest message body in UTF-8 bytes this daemon takes; absent on older daemons, which take 4096. */ + "value": Schema.Union([Schema.Struct({ "notes": Schema.Array(DirectiveNote), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "capabilities": Schema.Array(Capability), "event_cursor": Cursor, "grant_expires_at": optionalKey(Timestamp), "grant_id": optionalKey(Id), "grant_kind": optionalKey(Schema.Literals(["person","assistant"])), "kind": Schema.Literal("capabilities"), "limits": Schema.Struct({ "default_assistant_response_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(4096))), "max_arrangement_body_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_folders": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_key_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_name_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_operations": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_placements": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_resource_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangements": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_assistant_response_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(16384))), "max_event_items": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "max_glass_body_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glass_depth": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glass_nodes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glasses": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), /** The longest message body in UTF-8 bytes this daemon takes; absent on older daemons, which take 4096. */ "max_message_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))).annotate({ description: "The longest message body in UTF-8 bytes this daemon takes; absent on older daemons, which take 4096." }), "max_page_items": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "max_response_bytes": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1024)), "max_wait_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)) }), /** Compile-time build identity of the responding daemon; absent on older servers. */ -"machine_version": optionalKey(Schema.String).annotate({ description: "Compile-time build identity of the responding daemon; absent on older servers." }), "minimal_read_mode": optionalKey(AssistantMinimalReadMode), "oldest_event_cursor": Cursor, "policy_revision": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "principal": optionalKey(AssistantPrincipal), "schemas": Schema.Array(Schema.String.check(Schema.isPattern(URI_REFERENCE, { expected: "an RFC 3986 URI reference" }))).check(Schema.isMinLength(1)), "sender_class": optionalKey(AssistantSenderClass), "session_actor": Id, "transport": Schema.Literals(["unix","fabric-loopback"]), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "actions": Schema.Array(PrivateNotesAction).check(Schema.isMaxLength(1)), "data": PrivateNotesData, "family": Schema.Literal("private-notes"), "live": Schema.Null, "ref": PrivateNotesUri, "schema": Schema.Literal("fractal.private-notes@1"), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "bytes": Schema.Array(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(255))), "changed_at_unix_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "latest": optionalKey(Schema.Boolean), "name": optionalKey(Schema.String), "owner": optionalKey(Schema.String), "reference": Schema.String, "size": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "version": optionalKey(Schema.String), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "history": Schema.Boolean, "items": Schema.Array(DocumentItem), "limit": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "next_cursor": Schema.OptionFromOptionalNullOr(Schema.String, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), SchedulesPage, Schema.Struct({ "complete": Schema.Boolean, "references": Schema.Array(DocumentReference), "subject": Schema.String, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "conflicts": Schema.Array(Schema.String), "desired": Schema.suspend(() => CanonicalNode), "desired_revision": Revision, "desired_token": Schema.String.check(Schema.isMinCodePoints(1)), "kdl": Schema.String, "kind": Schema.Literal("subject-definition"), "subject": Schema.String.check(Schema.isPattern(new RegExp("^agent/[^\\s]+$", "u"))), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "declaration": Schema.Record(Schema.String, Schema.Unknown), "kind": Schema.Literal("publication-definition"), "revision": Revision, "subject": Schema.String.check(Schema.isPattern(new RegExp("^(agent|mission|schedule)/[^\\s]+$", "u"))), "token": Schema.String.check(Schema.isMinCodePoints(1)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Contains removed loop shapes that the current parser rejects. */ -"legacy": Schema.Boolean.annotate({ description: "Contains removed loop shapes that the current parser rejects." }), "mission": Schema.String.check(Schema.isPattern(new RegExp("^mission/[^\\s]+$", "u"))), "published_at": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "revision": Revision, "text": Schema.String, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "agent_id": AgentId, /** Agent declaration supplying the workspace; reached through unambiguous stop predecessors. */ +"machine_version": optionalKey(Schema.String).annotate({ description: "Compile-time build identity of the responding daemon; absent on older servers." }), "minimal_read_mode": optionalKey(AssistantMinimalReadMode), "oldest_event_cursor": Cursor, "policy_revision": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "principal": optionalKey(AssistantPrincipal), "schemas": Schema.Array(Schema.String.check(Schema.isPattern(URI_REFERENCE, { expected: "an RFC 3986 URI reference" }))).check(Schema.isMinLength(1)), "sender_class": optionalKey(AssistantSenderClass), "session_actor": Id, "transport": Schema.Literals(["unix","fabric-loopback"]), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "actions": Schema.Array(PrivateNotesAction).check(Schema.isMaxLength(1)), "data": PrivateNotesData, "family": Schema.Literal("private-notes"), "live": Schema.Null, "ref": PrivateNotesUri, "schema": Schema.Literal("fractal.private-notes@1"), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "bytes": Schema.Array(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(255))), "changed_at_unix_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "latest": optionalKey(Schema.Boolean), "name": optionalKey(Schema.String), "owner": optionalKey(Schema.String), "reference": Schema.String, "size": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "version": optionalKey(Schema.String), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "history": Schema.Boolean, "items": Schema.Array(DocumentItem), "limit": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "next_cursor": Schema.OptionFromOptionalNullOr(Schema.String, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), SchedulesPage, Schema.Struct({ "complete": Schema.Boolean, "references": Schema.Array(DocumentReference), "subject": Schema.String, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "conflicts": Schema.Array(Schema.String), "desired": Schema.suspend(() => CanonicalNode), "desired_revision": Revision, "desired_token": Schema.String.check(Schema.isMinCodePoints(1)), "kdl": Schema.String, "kind": Schema.Literal("subject-definition"), "subject": Schema.String.check(Schema.isPattern(new RegExp("^agent/[^\\s]+$", "u"))), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "declaration": Schema.Record(Schema.String, Schema.Unknown), "kind": Schema.Literal("publication-definition"), "revision": Revision, "subject": Schema.String.check(Schema.isPattern(new RegExp("^(agent|mission|schedule)/[^\\s]+$", "u"))), "token": Schema.String.check(Schema.isMinCodePoints(1)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Contains removed loop shapes that the current parser rejects. */ +"legacy": Schema.Boolean.annotate({ description: "Contains removed loop shapes that the current parser rejects." }), "mission": Schema.String.check(Schema.isPattern(new RegExp("^mission/[^\\s]+$", "u"))), "published_at": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "revision": Revision, "text": Schema.String, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "agent_id": AgentId, /** Agent declaration supplying the workspace; reached through unambiguous stop predecessors. */ "declaration_token": Schema.String.annotate({ description: "Agent declaration supplying the workspace; reached through unambiguous stop predecessors." }), /** Selected desired claim, including a stop when the seat is retired. */ "desired_token": Schema.String.annotate({ description: "Selected desired claim, including a stop when the seat is retired." }), "host_id": HostId, "kind": Schema.Literal("agent-workspace"), /** Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory. */ -"workspace": Schema.String.annotate({ description: "Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory." }), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.String.check(Schema.makeFilter((value: string) => !new RegExp("^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$", "u").test(value), { expected: "a string not matching ^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$" })), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(Resource), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("ordered-memberships"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(OrderedMembership), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("resources"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(ResourceObservation), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Resource, Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ -"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry), "kind": Schema.Literal("timeline-page"), "page": PageInfo, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ -"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-changes"), "next_cursor": Cursor, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "host_id": Id, "incomplete_sources": Schema.Array(Schema.String), "indexed_at": Timestamp, "items": Schema.Array(ConversationSearchHit).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-search"), "page": PageInfo, "refreshing": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "items": Schema.Array(ProjectionEvent).check(Schema.isMaxLength(500)), "kind": Schema.Literal("event-page"), "oldest_cursor": Cursor, "resume_cursor": Cursor, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "action_id": Id, "affected_ids": Schema.Array(Id).check(Schema.isUnique()), "arrangement_revision": optionalKey(Revision), "harness_answer": optionalKey(HarnessAnswerResult), "kind": Schema.Literal("action-result"), "membership_revision": optionalKey(Revision), "operation_id": Id, "private_notes": optionalKey(PrivateNotesFence), "snapshot_id": Id, "status": Schema.Literals(["accepted","completed","rejected"]), "terminal_attachment": Schema.OptionFromOptionalNullOr(TerminalAttachment, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "acknowledged_event_ids": Schema.Array(ClientDiagnosticUuid).check(Schema.isMaxLength(32)), "accounts": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), PairingChallenge, PairedSession, Schema.Struct({ "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, "expires_at": Timestamp, "id": Id, /** Daemon-configured owning person, sealed by the authoritative grant-issuer member at trusted-local begin. */ +"workspace": Schema.String.annotate({ description: "Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory." }), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.String.check(Schema.makeFilter((value: string) => !new RegExp("^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$", "u").test(value), { expected: "a string not matching ^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$" })), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(Resource), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("ordered-memberships"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(OrderedMembership), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("resources"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(ResourceObservation), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Resource, Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ +"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry), "kind": Schema.Literal("timeline-page"), "page": PageInfo, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ +"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-changes"), "next_cursor": Cursor, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "host_id": Id, "incomplete_sources": Schema.Array(Schema.String), "indexed_at": Timestamp, "items": Schema.Array(ConversationSearchHit).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-search"), "page": PageInfo, "refreshing": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "items": Schema.Array(ProjectionEvent).check(Schema.isMaxLength(500)), "kind": Schema.Literal("event-page"), "oldest_cursor": Cursor, "resume_cursor": Cursor, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "action_id": Id, "affected_ids": Schema.Array(Id).check(Schema.isUnique()), "arrangement_revision": optionalKey(Revision), "harness_answer": optionalKey(HarnessAnswerResult), "kind": Schema.Literal("action-result"), "membership_revision": optionalKey(Revision), "operation_id": Id, "private_notes": optionalKey(PrivateNotesFence), "snapshot_id": Id, "status": Schema.Literals(["accepted","completed","rejected"]), "terminal_attachment": Schema.OptionFromOptionalNullOr(TerminalAttachment, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "acknowledged_event_ids": Schema.Array(ClientDiagnosticUuid).check(Schema.isMaxLength(32)), "accounts": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), PairingChallenge, PairedSession, Schema.Struct({ /** Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing. */ +"cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing." }), /** Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses. */ +"conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, "expires_at": Timestamp, "id": Id, /** Daemon-configured owning person, sealed by the authoritative grant-issuer member at trusted-local begin. */ "issuer": PersonId, /** SHA-256 of the canonical device public-key string; never a credential digest. */ "key_id": Schema.String.check(Schema.isPattern(new RegExp("^[0-9a-f]{64}$", "u"))).annotate({ description: "SHA-256 of the canonical device public-key string; never a credential digest." }), "kind": Schema.Literal("assistant-grant"), "minimal_read_mode": AssistantMinimalReadMode, "policy_revision": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "principal": AssistantPrincipal, /** Owner-provisioned public pins for SCG read proofs. Absent means every assistant read is denied. */ "read_trust": optionalKey(AssistantReadTrust), /** Stored policy metadata; does not restrict message.send. write.assistant.messages permits any existing agent recipient, never a person. */ -"recipient_allowlist": Schema.Array(Schema.String.check(Schema.isPattern(new RegExp("^agent/.+$", "u")))).annotate({ description: "Stored policy metadata; does not restrict message.send. write.assistant.messages permits any existing agent recipient, never a person." }), "revoked": Schema.Boolean, "scopes": Schema.Array(AssistantScope).check(Schema.isMinLength(1)).check(Schema.isUnique()), "sender_class": AssistantSenderClass, "session_actor": Schema.String.check(Schema.isPattern(new RegExp("^assistant/(?:chatgpt|mcp)/session/.+$", "u"))), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "as_of": Timestamp, "counts": Schema.Struct({ "agent_states": Schema.Record(Schema.String, Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "attention": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "mission_states": Schema.Record(Schema.String, Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))) }), "kind": Schema.Literal("assistant-summary"), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.attention"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantAttentionItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.missions"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantMissionItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.agents"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantAgentItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), AssistantContentPage, Schema.Struct({ "columns": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "cursor": Schema.Struct({ "blinking": Schema.Boolean, "column": Schema.Int, "row": Schema.Int, "style": Schema.Literals(["block","underline","bar"]), "visible": Schema.Boolean }), "facts": optionalKey(TerminalFacts), "kind": Schema.Literal("terminal-screen"), "lines": Schema.Array(TerminalLine), "modes": TerminalModes, /** Fence for the next input or resize. */ +"recipient_allowlist": Schema.Array(Schema.String.check(Schema.isPattern(new RegExp("^agent/.+$", "u")))).annotate({ description: "Stored policy metadata; does not restrict message.send. write.assistant.messages permits any existing agent recipient, never a person." }), "revoked": Schema.Boolean, "scopes": Schema.Array(AssistantScope).check(Schema.isMinLength(1)).check(Schema.isUnique()), "sender_class": AssistantSenderClass, "session_actor": Schema.String.check(Schema.isPattern(new RegExp("^assistant/(?:chatgpt|mcp)/session/.+$", "u"))), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "as_of": Timestamp, "counts": Schema.Struct({ "agent_states": Schema.Record(Schema.String, Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "attention": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "mission_states": Schema.Record(Schema.String, Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))) }), "kind": Schema.Literal("assistant-summary"), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.attention"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantAttentionItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.missions"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantMissionItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.agents"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantAgentItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), AssistantContentPage, Schema.Struct({ "columns": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "cursor": Schema.Struct({ "blinking": Schema.Boolean, "column": Schema.Int, "row": Schema.Int, "style": Schema.Literals(["block","underline","bar"]), "visible": Schema.Boolean }), "facts": optionalKey(TerminalFacts), "kind": Schema.Literal("terminal-screen"), "lines": Schema.Array(TerminalLine), "modes": TerminalModes, /** Fence for the next input or resize. */ "next_sequence": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).annotate({ description: "Fence for the next input or resize." }), "relay": optionalKey(TerminalRelay), /** Digest of the rest of the screen: equal revisions mean equal screens. */ -"revision": Schema.String.check(Schema.isMinCodePoints(1)).pipe(Schema.brand("st3/ScreenRevision")).annotate({ description: "Digest of the rest of the screen: equal revisions mean equal screens." }), "rows": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "runtime_incarnation": Schema.String, "terminal_id": TerminalId, "title": Schema.String, "truncated": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "complete": Schema.Boolean, "items": Schema.Array(StatusTransition).check(Schema.isMaxLength(200)), "kind": Schema.Literal("status-history"), "retained_from": Timestamp, "seat": AgentId, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "agent_id": Id, "current_work_ids": Schema.Array(Id), "kind": Schema.Literal("agent-queue"), "move_count": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "moves": Schema.Array(AgentQueueMove), "next_work_id": Schema.OptionFromNullOr(Id), "runs": Schema.Array(AgentQueueRun), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), AgentRelatedRuns, Schema.Struct({ /** Every declared account in name order, so each panel lists the same accounts. Absent on older servers. */ -"accounts": optionalKey(Schema.Array(UsageAccount)).annotate({ description: "Every declared account in name order, so each panel lists the same accounts. Absent on older servers." }), "agent_messages": optionalKey(AgentMessageEstimate), "limits": optionalKey(Schema.Array(UsageLimit)), "rows": Schema.Array(UsageRow), "since_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "until_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "cleanup_command": Schema.String, "count": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "threshold_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "as_of_unix_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), /** Where a person reads the exported observation history, from the daemon's [observations.otlp] ui_url. Absent when none is configured. */ -"otel_ui_url": optionalKey(Schema.String).annotate({ description: "Where a person reads the exported observation history, from the daemon's [observations.otlp] ui_url. Absent when none is configured." }), "rows": Schema.Array(SloRow), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "id": Schema.String, "samples": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "since_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "steps": Schema.Array(Schema.NullOr(Schema.Number.check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)))), "until_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) })], { mode: "oneOf" }) +"revision": Schema.String.check(Schema.isMinCodePoints(1)).pipe(Schema.brand("st3/ScreenRevision")).annotate({ description: "Digest of the rest of the screen: equal revisions mean equal screens." }), "rows": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "runtime_incarnation": Schema.String, "terminal_id": TerminalId, "title": Schema.String, "truncated": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "complete": Schema.Boolean, "items": Schema.Array(StatusTransition).check(Schema.isMaxLength(200)), "kind": Schema.Literal("status-history"), "retained_from": Timestamp, "seat": AgentId, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "agent_id": Id, "current_work_ids": Schema.Array(Id), "kind": Schema.Literal("agent-queue"), "move_count": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "moves": Schema.Array(AgentQueueMove), "next_work_id": Schema.OptionFromNullOr(Id), "runs": Schema.Array(AgentQueueRun), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), AgentRelatedRuns, Schema.Struct({ /** Every declared account in name order, so each panel lists the same accounts. Absent on older servers. */ +"accounts": optionalKey(Schema.Array(UsageAccount)).annotate({ description: "Every declared account in name order, so each panel lists the same accounts. Absent on older servers." }), "agent_messages": optionalKey(AgentMessageEstimate), "limits": optionalKey(Schema.Array(UsageLimit)), "rows": Schema.Array(UsageRow), "since_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "until_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "cleanup_command": Schema.String, "count": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "threshold_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "as_of_unix_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), /** Where a person reads the exported observation history, from the daemon's [observations.otlp] ui_url. Absent when none is configured. */ +"otel_ui_url": optionalKey(Schema.String).annotate({ description: "Where a person reads the exported observation history, from the daemon's [observations.otlp] ui_url. Absent when none is configured." }), "rows": Schema.Array(SloRow), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "id": Schema.String, "samples": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "since_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "steps": Schema.Array(Schema.NullOr(Schema.Number.check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)))), "until_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) })], { mode: "oneOf" }) }).annotate({ identifier: "Envelope" }))() export type Envelope = typeof Envelope.Type export type EnvelopeEncoded = typeof Envelope.Encoded @@ -1000,6 +1036,8 @@ export const ErrorEnvelope = /*#__PURE__*/ (() => Schema.Union([ Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("peer-too-old"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("validation-failed"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("idempotency-conflict"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), + Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("grant-profile-conflict"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), + Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("assistant-grant-authority-not-ready"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("legacy-action-receipt-untrusted"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("issuer-required"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("pairing-origin-required"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), @@ -1044,7 +1082,7 @@ export const ErrorEnvelope = /*#__PURE__*/ (() => Schema.Union([ Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("invalid-answer"), "details": HarnessInvalidAnswerDetails, "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("not-answerable"), "details": HarnessNotAnswerableDetails, "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("internal"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), - Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": unknownCase(["recipient-retired","agents-publication-row-too-large","identity-cycle","identity-occupied","identity-retired-source","identity-cross-kind","identity-unknown","lifecycle-unavailable","retirement-upgrade-required","retire-revision-mismatch","retire-incarnation-mismatch","invalid-custody-successor","custody-pending","attention-migrated","arrangement-exists","arrangement-folder-exists","arrangement-retired","arrangement-limit","arrangement-folder-deleted","arrangement-cycle","arrangement-body-too-large","arrangement-owner-forbidden","invalid-arrangement-subject","invalid-arrangement-action","invalid-arrangement-operations","invalid-arrangement-folder","invalid-arrangement-name","invalid-arrangement-key","invalid-arrangement-version","invalid-arrangement-body","unsupported-membership-container","membership-owner-forbidden","invalid-membership-member","invalid-membership-bucket","invalid-membership-key","invalid-membership-operations","membership-edit-too-large","invalid-subject-reference","not-found","forbidden","unsupported-capability","peer-too-old","validation-failed","idempotency-conflict","legacy-action-receipt-untrusted","issuer-required","pairing-origin-required","pairing-restart-required","suspend-authored-session-selection","stale-fence","cursor-gap","page-cursor-expired","agent-roster-not-ready","agent-roster-cut-not-ready","message-selectors-not-ready","rate-limited","runtime-not-local","runtime-authority-indeterminate","runtime-list-not-ready","runtime-list-ended","remote-unavailable","terminal-unavailable","inventory-unavailable","terminal-ended","timeline-history-incomplete","projection-detail-too-large","projection-detail-invalid-source","conversation-content-invalidated","transcript-unavailable","blob-too-large","unsupported-media-type","blob-content-mismatch","blob-quota-exceeded","blob-not-found","blob-expired","message-too-large","message-store-full","long-message-signature-unsupported","response-budget-exceeded","content-not-text","invalid-document-reference","document-not-synced","private-notes-unreachable","private-notes-carrier-conflict","private-notes-indeterminate","invalid-answer","not-answerable","internal"]), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }) + Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": unknownCase(["recipient-retired","agents-publication-row-too-large","identity-cycle","identity-occupied","identity-retired-source","identity-cross-kind","identity-unknown","lifecycle-unavailable","retirement-upgrade-required","retire-revision-mismatch","retire-incarnation-mismatch","invalid-custody-successor","custody-pending","attention-migrated","arrangement-exists","arrangement-folder-exists","arrangement-retired","arrangement-limit","arrangement-folder-deleted","arrangement-cycle","arrangement-body-too-large","arrangement-owner-forbidden","invalid-arrangement-subject","invalid-arrangement-action","invalid-arrangement-operations","invalid-arrangement-folder","invalid-arrangement-name","invalid-arrangement-key","invalid-arrangement-version","invalid-arrangement-body","unsupported-membership-container","membership-owner-forbidden","invalid-membership-member","invalid-membership-bucket","invalid-membership-key","invalid-membership-operations","membership-edit-too-large","invalid-subject-reference","not-found","forbidden","unsupported-capability","peer-too-old","validation-failed","idempotency-conflict","grant-profile-conflict","assistant-grant-authority-not-ready","legacy-action-receipt-untrusted","issuer-required","pairing-origin-required","pairing-restart-required","suspend-authored-session-selection","stale-fence","cursor-gap","page-cursor-expired","agent-roster-not-ready","agent-roster-cut-not-ready","message-selectors-not-ready","rate-limited","runtime-not-local","runtime-authority-indeterminate","runtime-list-not-ready","runtime-list-ended","remote-unavailable","terminal-unavailable","inventory-unavailable","terminal-ended","timeline-history-incomplete","projection-detail-too-large","projection-detail-invalid-source","conversation-content-invalidated","transcript-unavailable","blob-too-large","unsupported-media-type","blob-content-mismatch","blob-quota-exceeded","blob-not-found","blob-expired","message-too-large","message-store-full","long-message-signature-unsupported","response-budget-exceeded","content-not-text","invalid-document-reference","document-not-synced","private-notes-unreachable","private-notes-carrier-conflict","private-notes-indeterminate","invalid-answer","not-answerable","internal"]), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }) ], { mode: "oneOf" }).annotate({ identifier: "ErrorEnvelope" }))() export type ErrorEnvelope = typeof ErrorEnvelope.Type export type ErrorEnvelopeEncoded = typeof ErrorEnvelope.Encoded diff --git a/crates/fractal-api-client-v0/src/api/client_v0.rs b/crates/fractal-api-client-v0/src/api/client_v0.rs index 0e38688024a..3a00515957b 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0.rs @@ -3934,6 +3934,9 @@ fn operation_resources(state: &AppState, at: &str) -> Result, ApiErro }; let mut values = checks .iter() + // Grant IDs and issuing identities are trusted-local doctor diagnostics, not + // projection data for paired clients. Both collection and detail use this list. + .filter(|check| check.name != "assistant-grant-provenance") .map(|check| { let digest = hex::encode(Sha256::digest(check.name.as_bytes())); json!({ @@ -13751,6 +13754,69 @@ mission "differential" state="ready" { } } + #[tokio::test] + async fn paired_operations_do_not_disclose_local_doctor_grant_provenance() { + let root = tempfile::tempdir().unwrap(); + let state = test_state(root.path()); + let credential = "operations-provenance-reader"; + state.store.append_client_operation_claim(&ClaimInput { + subject: "custom/client/operations-provenance-reader".into(), + kind: "custom.client.pairing-completed".into(), + actor: Some("person/ada".into()), + fields: BTreeMap::from([ + ("credential_hash".into(), json!(credential_digest(credential))), + ("session_actor".into(), json!("client/operations-provenance-reader")), + ("person_id".into(), json!("person/ada")), + ("scopes".into(), json!(["read.projections"])), + ("expires_at_unix_ms".into(), json!(client_now_ms() as u64 + 60_000)), + ]), + evidence: Vec::new(), expected_subject: None, idempotency_key: None, + }).unwrap(); + let grant_id = "claim/private-doctor-grant"; + let origin = "private-doctor-origin"; + let issuer = "person/private-doctor-issuer"; + state.store.connection.write().execute( + "INSERT INTO assistant_grant_pending + (claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) + VALUES(?1,?1,'custom.client.assistant.v1.granted',?2,?3,1,0,'{}')", + rusqlite::params![grant_id, origin, issuer], + ).unwrap(); + let checks = doctor_report(&state).unwrap().0.checks; + let provenance = checks.iter() + .find(|check| check.name == "assistant-grant-provenance").unwrap(); + for private in [grant_id, origin, issuer] { + assert!(provenance.message.contains(private), "{provenance:?}"); + } + // Serve exactly the detailed local report through the remote projection paths. + operation_reports().insert( + Arc::as_ptr(&state.store) as usize, + OperationReport { + store: Arc::downgrade(&state.store), checks: Some(Arc::new(checks)), + at: Instant::now(), refreshing: false, + }, + ); + let digest = hex::encode(Sha256::digest(b"assistant-grant-provenance")); + let app = super::super::fabric_router(state.clone()); + for (uri, expected) in [ + ("/v1/client/operations".to_owned(), StatusCode::OK), + (format!("/v1/client/operations/diagnostic-{}", &digest[..16]), StatusCode::NOT_FOUND), + ] { + let request = Request::builder().uri(uri) + .header(AUTHORIZATION, format!("Bearer {credential}")) + .body(Body::empty()).unwrap(); + let session = authenticate(&state, &request, "fabric-loopback").unwrap(); + assert!(session.allows("read.projections")); + assert!(!session.local_peer); + let response = app.clone().oneshot(request).await.unwrap(); + assert_eq!(response.status(), expected); + let bytes = to_bytes(response.into_body(), CLIENT_MAX_RESPONSE_BYTES).await.unwrap(); + let body = std::str::from_utf8(&bytes).unwrap(); + for private in [grant_id, origin, issuer, "assistant-grant-provenance"] { + assert!(!body.contains(private), "{body}"); + } + } + } + #[tokio::test] async fn fleet_operational_commands_are_bounded_and_report_slow_queries() { use crate::OperationsFixtureStore; diff --git a/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs b/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs index 43f06a2dc19..02cf43b48dc 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs @@ -6,6 +6,7 @@ pub use native::propose; pub use authorization::{ReadReceipt, finish as finish_read, pin as pin_read_trust, read as read_projection}; pub use fractal_api_core::api::client_v0::assistant::*; pub use fractal_api_core::api::client_v0::assistant::{PRINCIPAL, append, authenticate, authorize_route, device_resources, trusted_issuer}; +use fractal_api_core::api::client_v0::external_grants::{projection_with_witness, revoked}; pub mod authorization; pub mod native; pub mod reads; @@ -208,12 +209,22 @@ async fn complete_inner(state: &AppState, id: &str, request: &PairingComplete, "grant":projection})))) } +#[derive(Default, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct AssistantGrantQuery { + witness: Option, +} + pub async fn inspect(State(state): State, Extension(session): Extension, - AxumPath(id): AxumPath) -> Result, ApiError> { + AxumPath(id): AxumPath, Query(query): Query) -> Result, ApiError> { trusted_issuer(&state, &session)?; let granted = latest(&state, &subject(&id)?, GRANTED)? .ok_or_else(|| ApiError::not_found("assistant grant does not exist"))?; - Ok(Json(projection(&state, &granted)?)) + Ok(Json(if query.witness.as_deref() == Some("1") { + projection_with_witness(&state, &granted)? + } else { + projection(&state, &granted)? + })) } async fn revoke_inner(State(state): State, Extension(session): Extension, @@ -226,11 +237,18 @@ async fn revoke_inner(State(state): State, Extension(session): Extensi if granted.origin != state.store.origin() { return Err(forbidden("assistant revocation must run on its authoritative issuer")); } - if latest(&state, &subject, REVOKED)?.is_none() { + if !revoked(&state, &granted)? { let previous = effective(&state, &granted)?; - append(&state, subject, REVOKED, issuer, json!({"version":1,"grant_id":fields(&granted)?["grant_id"], - "principal":principal(fields(&granted)?)?,"issuer":issuer,"transport":session.transport, - "timestamp":client_timestamp(client_now_ms()),"outcome":"revoked"}), Some(&previous))?; + let source = fields(&granted)?; + let mut value = json!({"version":1,"grant_id":source["grant_id"], + "principal":principal(source)?,"issuer":issuer,"transport":session.transport, + "timestamp":client_timestamp(client_now_ms()),"outcome":"revoked"}); + // Revocation is not issuance: retain the immutable profile, including + // the absence of a profile on legacy assistant grants. + if let Some(profile) = source.get("profile") { + value["profile"] = profile.clone(); + } + append(&state, subject, REVOKED, issuer, value, Some(&previous))?; signal_changed(&state); } Ok(Json(projection(&state, &granted)?)) @@ -252,7 +270,7 @@ async fn update_policy_inner(State(state): State, Extension(session): if granted.origin != state.store.origin() { return Err(forbidden("assistant policy must change on its authoritative issuer")); } - if latest(&state, &subject, REVOKED)?.is_some() { return Err(forbidden("assistant grant was revoked")); } + if revoked(&state, &granted)? { return Err(forbidden("assistant grant was revoked")); } let previous = effective(&state, &granted)?; // Policy changes must not revive an expired grant: fail closed instead of extending it. if fields(&previous)?["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) <= client_now_ms() { @@ -306,6 +324,68 @@ mod tests { &request, "fabric-loopback").await.unwrap().unwrap().0 } + fn seeded_grant(state: &AppState, profile: Option<&str>) -> ClaimRecord { + let id = "111111111111111111111111"; + let mut source = json!({"version":1,"grant_id":format!("assistant-grant/{id}"), + "principal":PRINCIPAL,"sender_class":"external-assistant","issuer":ISSUER, + "session_actor":format!("{PRINCIPAL}/session/assistant-grant/{id}"), + "credential_hash":credential_digest("reserved-service-credential"), + "device_id":"device/service-history","key_id":"service-history", + "scopes":SCOPES[..4],"expires_at_unix_ms":client_now_ms()+3_600_000, + "policy_revision":1,"minimal_read_mode":"approval-once","recipient_allowlist":[], + "disclosure_consent":true,"consent_evidence":"recorded owner consent"}); + if let Some(profile) = profile { + source["profile"] = json!(profile); + } + // Retain pre-existing evidence without opening the production issuance gate. + state.store.append_claim(&ClaimInput { + subject: subject(id).unwrap(), kind: GRANTED.into(), actor: Some(ISSUER.into()), + fields: serde_json::from_value(source).unwrap(), evidence: Vec::new(), + expected_subject: None, idempotency_key: None, + }).unwrap() + } + + #[tokio::test] + async fn owner_revoke_endpoint_preserves_profiles_and_is_idempotent() { + use axum::{body::{Body, to_bytes}, http::Request}; + use tower::ServiceExt; + + for profile in [None, Some("assistant"), Some("service")] { + let root = tempfile::tempdir().unwrap(); + let state = state(root.path()); + let granted = seeded_grant(&state, profile); + let app = super::super::super::router_for_transport(state.clone(), + ClientTransportBoundary::Unix, &[crate::api::client_v0::routes]); + let path = "/v1/client/assistant/grants/111111111111111111111111/revoke"; + // An arbitrary local person must not gain the owner's revocation right. + let mut denied = Request::builder().method("POST").uri(path) + .header(LOCAL_PERSON_HEADER, "person/other").body(Body::empty()).unwrap(); + denied.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + assert_eq!(app.clone().oneshot(denied).await.unwrap().status(), StatusCode::FORBIDDEN); + assert!(latest(&state, &granted.subject, REVOKED).unwrap().is_none()); + + let mut revocation_id = None; + for _ in 0..2 { + let mut request = Request::builder().method("POST").uri(path) + .header(LOCAL_PERSON_HEADER, ISSUER).body(Body::empty()).unwrap(); + request.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + let response = app.clone().oneshot(request).await.unwrap(); + assert_eq!(response.status(), StatusCode::OK, "{profile:?}"); + let body: Value = serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap()).unwrap(); + assert_eq!(body["value"]["revoked"], true); + let revoked = latest(&state, &granted.subject, REVOKED).unwrap().unwrap(); + assert_eq!(fields(&revoked).unwrap().get("profile"), fields(&granted).unwrap().get("profile")); + assert_eq!(revoked.actor.as_deref(), Some(ISSUER)); + assert_eq!(revoked.origin, granted.origin); + if let Some(id) = &revocation_id { + assert_eq!(&revoked.id, id, "repeat revocation must not append another transition"); + } else { + revocation_id = Some(revoked.id); + } + } + } + } + async fn begin_assistant(state: &AppState) -> Value { begin(state.clone(), ClientSession::local(Some(ISSUER)).unwrap(), request()).await.unwrap().0 } @@ -364,6 +444,112 @@ mod tests { } } + #[tokio::test] + async fn service_history_does_not_enable_issuance_policy_or_requests() { + use axum::{body::Body, http::Request}; + use tower::ServiceExt; + + let root = tempfile::tempdir().unwrap(); + let state = state(root.path()); + let granted = seeded_grant(&state, Some("service")); + let app = super::super::super::router_for_transport(state.clone(), + ClientTransportBoundary::Unix, &[crate::api::client_v0::routes]); + for path in ["/v1/client/assistant/summary", "/v1/client/capabilities"] { + let request = Request::builder().uri(path) + .header(AUTHORIZATION, "Bearer reserved-service-credential") + .body(Body::empty()).unwrap(); + assert_eq!(app.clone().oneshot(request).await.unwrap().status(), StatusCode::FORBIDDEN); + } + let policy = json!({"api_version":CLIENT_API_VERSION,"scopes":SCOPES[..4], + "expires_in_seconds":3600,"disclosure_consent":true, + "consent_evidence":"recorded owner consent","minimal_read_mode":"approval-once"}); + let mut request = Request::builder().method("POST") + .uri("/v1/client/assistant/grants/111111111111111111111111/policy") + .header(LOCAL_PERSON_HEADER, ISSUER).header("content-type", "application/json") + .body(Body::from(policy.to_string())).unwrap(); + request.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + assert_eq!(app.clone().oneshot(request).await.unwrap().status(), StatusCode::FORBIDDEN); + assert!(latest(&state, &granted.subject, POLICY).unwrap().is_none()); + + let issuance = json!({"api_version":CLIENT_API_VERSION,"device_name":"service", + "assistant_id":PRINCIPAL,"profile":"service","scopes":SCOPES[..4], + "expires_in_seconds":3600,"disclosure_consent":true, + "consent_evidence":"recorded owner consent"}); + let mut request = Request::builder().method("POST").uri("/v1/client/pairings") + .header(LOCAL_PERSON_HEADER, ISSUER).header("content-type", "application/json") + .body(Body::from(issuance.to_string())).unwrap(); + request.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + assert_eq!(app.oneshot(request).await.unwrap().status(), StatusCode::UNPROCESSABLE_ENTITY); + assert!(state.store.claims_for_kind_at(BEGUN, None, true, 10).unwrap().claims.is_empty()); + } + + // Frozen pre-witness shape, independent of today's generated grant model. + #[derive(Deserialize)] + #[serde(deny_unknown_fields)] + #[allow(dead_code)] + struct LegacyAssistantGrant { + kind: String, + id: String, + principal: String, + sender_class: String, + session_actor: String, + device_id: String, + key_id: String, + issuer: String, + scopes: Vec, + expires_at: String, + policy_revision: u64, + minimal_read_mode: String, + recipient_allowlist: Vec, + disclosure_consent: bool, + consent_evidence: String, + revoked: bool, + read_trust: Option, + } + + #[tokio::test] + async fn grant_responses_preserve_strict_legacy_shape_unless_inspect_opts_in() { + use axum::{body::{Body, to_bytes}, http::Request}; + use tower::ServiceExt; + + let root = tempfile::tempdir().unwrap(); + let state = state(root.path()); + let paired = paired(&state).await; + serde_json::from_value::(paired["grant"].clone()).unwrap(); + let id = paired["grant"]["id"].as_str().unwrap(); + let app = super::super::super::router_for_transport(state.clone(), ClientTransportBoundary::Unix, &[crate::api::client_v0::routes]); + for query in ["", "?witness=0", "?witness=true", "?witness=1"] { + let mut request = Request::builder() + .uri(format!("/v1/client/assistant/grants/{}{query}", urlencoding::encode(id))) + .header(LOCAL_PERSON_HEADER, ISSUER).body(Body::empty()).unwrap(); + request.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + let response = app.clone().oneshot(request).await.unwrap(); + assert_eq!(response.status(), StatusCode::OK); + let body: Value = serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap()).unwrap(); + let grant = body["value"].clone(); + if query == "?witness=1" { + assert_eq!(grant["conflict"], Value::Null); + assert!(grant["cleared_conflicts"].is_array()); + assert!(serde_json::from_value::(grant).is_err()); + } else { + serde_json::from_value::(grant).unwrap(); + } + } + let policy = serde_json::from_value(json!({ + "api_version": CLIENT_API_VERSION, "scopes": SCOPES[..4], + "disclosure_consent": true, "consent_evidence": "owner approved renewal", + "minimal_read_mode": "approval-once" + })).unwrap(); + let Json(changed) = update_policy(State(state.clone()), + Extension(ClientSession::local(Some(ISSUER)).unwrap()), + AxumPath(id.into()), Json(policy)).await.unwrap(); + serde_json::from_value::(changed).unwrap(); + let Json(revoked) = revoke(State(state), + Extension(ClientSession::local(Some(ISSUER)).unwrap()), + AxumPath(id.into())).await.unwrap(); + serde_json::from_value::(revoked).unwrap(); + } + #[tokio::test] async fn legacy_assistant_pairing_requires_an_unexpired_bounded_lifetime() { for (lifetime, accepted) in [(299_000_i64,true),(300_000,true),(300_001,false),(600_000,false),(-1,false)] { @@ -549,7 +735,8 @@ mod tests { value["principal"] = json!(replacement); value["session_actor"] = json!(format!("{replacement}/session/{}", paired["grant"]["id"].as_str().unwrap())); append(&state, granted.subject.clone(), POLICY, ISSUER, value, Some(&granted)).unwrap(); - assert!(authenticate(&state, &credential_digest(paired["credential"].as_str().unwrap()), "fabric-loopback").is_err()); + let session = authenticate(&state, &credential_digest(paired["credential"].as_str().unwrap()), "fabric-loopback").unwrap().unwrap(); + assert_eq!(session.authority_actor, principal); } } } @@ -702,6 +889,39 @@ mod tests { assert!(!String::from_utf8(body.to_vec()).unwrap().contains("max_message_bytes")); } + #[tokio::test] + async fn authority_backfill_refusal_is_typed_retryable_and_recovers() { + let root = tempfile::tempdir().unwrap(); + let state = state(root.path()); + let paired = paired(&state).await; + state.store.connection.write().execute( + "DELETE FROM meta WHERE key='assistant_grant_authority_version'", [], + ).unwrap(); + let app = super::super::super::router_for_transport( + state.clone(), ClientTransportBoundary::Unix, &[crate::api::client_v0::routes], + ); + let inspect = format!("/v1/client/assistant/grants/{}", + urlencoding::encode(paired["grant"]["id"].as_str().unwrap())); + for (path, bearer) in [("/v1/client/assistant/summary", true), (inspect.as_str(), false)] { + let mut request = Request::builder().uri(path); + if bearer { + request = request.header(AUTHORIZATION, + format!("Bearer {}", paired["credential"].as_str().unwrap())); + } else { + request = request.header(LOCAL_PERSON_HEADER, ISSUER); + } + let response = app.clone().oneshot(request.body(Body::empty()).unwrap()).await.unwrap(); + assert_eq!(response.status(), StatusCode::SERVICE_UNAVAILABLE); + let body = axum::body::to_bytes(response.into_body(), usize::MAX).await.unwrap(); + let value: Value = serde_json::from_slice(&body).unwrap(); + assert_eq!(value["code"], "assistant-grant-authority-not-ready"); + assert_eq!(value["retryable"], true); + } + while !state.store.advance_assistant_grant_authority_backfill().unwrap() {} + assert!(authenticate(&state, + &credential_digest(paired["credential"].as_str().unwrap()), "unix").unwrap().is_some()); + } + #[tokio::test] async fn assistant_revocation_and_expiry_survive_restart() { let root=tempfile::tempdir().unwrap(); let state1=state(root.path()); let paired1=paired(&state1).await; @@ -822,7 +1042,7 @@ mod tests { assert_eq!(fs::metadata(&profile).unwrap().permissions().mode() & 0o777,0o600); assert!(!root.path().join("devices.json").exists()); let Json(grant)=inspect(State(state),Extension(ClientSession::local(Some(ISSUER)).unwrap()), - AxumPath(device.session.grant.id)).await.unwrap(); + AxumPath(device.session.grant.id), Query(AssistantGrantQuery::default())).await.unwrap(); assert_eq!(grant["principal"],PRINCIPAL); server.abort(); } diff --git a/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs b/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs index e75938f58f2..00299ebb8ac 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs @@ -101,6 +101,108 @@ async fn request(app: Router, credential: &str, method: &str, path: &str, header (status,serde_json::from_slice(&bytes).unwrap(),bytes.len()) } +#[tokio::test] +async fn p1_owner_transitions_ignore_wrong_origin_overlays_but_fence_the_subject_head() { + for kind in [POLICY, REVOKED] { + let fixture = fixture(SCOPES, false).await; + let subject = subject(&fixture.grant).unwrap(); + let granted = latest(&fixture.state, &subject, GRANTED).unwrap().unwrap(); + let peer = Store::open_memory("wrong-origin").unwrap(); + // These overlays must be authenticated data from the wrong issuer. + // An unsigned import instead fences the subject until it authenticates. + const FLEET: &str = "86700000-0000-4000-8000-000000000001"; + let anchor = Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0); + let peer_key = Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0); + for store in [&*fixture.state.store, &peer] { + store.bind_fleet(FLEET).unwrap(); + store.pin_fleet_anchor(anchor.public()).unwrap(); + } + fixture.state.store.set_member_key(Some(anchor.clone())).unwrap(); + peer.set_member_key(Some(peer_key.clone())).unwrap(); + fixture.state.store.admit_fleet_anchor(FLEET, anchor.public(), "listening").unwrap(); + fixture.state.store.append_claim(&ClaimInput { + subject: "host/wrong-origin".into(), kind: "fleet.member-admitted".into(), + actor: Some(OWNER.into()), + fields: serde_json::from_value(json!({ + "fleet_id": FLEET, "member_key": peer_key.public(), + "via": "invite", "mode": "listening", "writer_floor": 0, + })).unwrap(), + evidence: Vec::new(), expected_subject: None, idempotency_key: None, + }).unwrap(); + let replicate = |from: &Store, to: &Store| { + let exchange = from.export_replication_exchange_answering( + FLEET, &to.replication_inventory().unwrap(), + &to.replication_signature_requests().unwrap(), + ).unwrap(); + to.receive_replication_exchange(from.origin(), FLEET, &exchange).unwrap(); + to.validate_replication_backlog().unwrap(); + to.project_replication_backlog().unwrap(); + }; + replicate(&fixture.state.store, &peer); + while !peer.advance_assistant_grant_authority_backfill().unwrap() {} + while !fixture.state.store.advance_assistant_grant_authority_backfill().unwrap() {} + let overlay = || { + let mut value = fields(&granted).unwrap().clone(); + if kind == POLICY { + value["policy_revision"] = json!(999); + value["expires_at_unix_ms"] = json!(1); + value["scopes"] = json!([]); + } + let claim = peer.append_claim(&ClaimInput { + subject: subject.clone(), kind: kind.into(), actor: Some(OWNER.into()), + fields: serde_json::from_value(value).unwrap(), evidence: Vec::new(), + expected_subject: None, idempotency_key: None, + }).unwrap(); + replicate(&peer, &fixture.state.store); + assert!(fixture.state.store.claim_by_id(&claim.id).unwrap().is_some(), + "wrong-origin evidence must remain in raw history without becoming authority"); + assert!(authenticate(&fixture.state, &credential_digest(&fixture.credential), "fabric-loopback").unwrap().is_none(), + "receipt must fence the subject before background authentication"); + while !fixture.state.store.advance_assistant_grant_authority_backfill().unwrap() {} + assert!(fixture.state.store.claim_has_authenticated_member_writer(&claim.id).unwrap(), + "wrong-origin filtering must be exercised after writer authentication"); + assert!(authenticate(&fixture.state, &credential_digest(&fixture.credential), "fabric-loopback").unwrap().is_some()); + }; + + overlay(); + let policy = serde_json::from_value::(json!({ + "api_version": CLIENT_API_VERSION, "scopes": SCOPES, "expires_in_seconds": 86400, + "disclosure_consent": true, "consent_evidence": "recorded owner consent", + "minimal_read_mode": "approval-once", + })).unwrap(); + let Json(renewed) = update_policy(State(fixture.state.clone()), + Extension(ClientSession::local(Some(OWNER)).unwrap()), AxumPath(fixture.grant.clone()), + Json(policy)).await.unwrap(); + assert_eq!(renewed["policy_revision"], 2); + assert_eq!(renewed["revoked"], false); + let renewed_claim = effective(&fixture.state, &granted).unwrap(); + assert_eq!(renewed_claim.body["evidence"], json!([granted.id])); + + overlay(); + let Json(pinned) = pin(State(fixture.state.clone()), + Extension(ClientSession::local(Some(OWNER)).unwrap()), AxumPath(fixture.grant.clone()), + Json(fixture.trust_request())).await.unwrap(); + assert_eq!(pinned["policy_revision"], 3); + assert_eq!(pinned["read_trust"]["key_id"], "approval-key/test"); + let pinned_claim = effective(&fixture.state, &granted).unwrap(); + assert_eq!(pinned_claim.body["evidence"], json!([renewed_claim.id])); + + overlay(); + let Json(revoked) = revoke(State(fixture.state.clone()), + Extension(ClientSession::local(Some(OWNER)).unwrap()), + AxumPath(fixture.grant.clone())).await.unwrap(); + assert_eq!(revoked["revoked"], true); + let revocation = latest(&fixture.state, &subject, REVOKED).unwrap().unwrap(); + assert_eq!(revocation.origin, granted.origin); + assert_eq!(revocation.body["evidence"], json!([pinned_claim.id])); + assert!(authenticate(&fixture.state, &credential_digest(&fixture.credential), "fabric-loopback").is_err()); + assert_eq!(fixture.request("/v1/client/assistant/summary", None).await.0, StatusCode::FORBIDDEN); + assert_eq!(pin(State(fixture.state.clone()), Extension(ClientSession::local(Some(OWNER)).unwrap()), + AxumPath(fixture.grant.clone()), Json(fixture.trust_request())).await.unwrap_err().status, + StatusCode::FORBIDDEN); + } +} + #[tokio::test] async fn scg_read_accepts_header_aliases_and_binds_presented_domain() { let fixture = fixture(SCOPES, true).await; diff --git a/crates/fractal-api-core/src/api.rs b/crates/fractal-api-core/src/api.rs index ad99a2daaa3..71ad6e6a7b5 100644 --- a/crates/fractal-api-core/src/api.rs +++ b/crates/fractal-api-core/src/api.rs @@ -477,6 +477,7 @@ impl ApiError { | "stale-subject" | "stale-fence" | "idempotency-conflict" + | "grant-profile-conflict" | "private-notes-carrier-conflict" | "owned-set-refused" | "set-managed-subject" @@ -498,6 +499,7 @@ impl ApiError { "identity-unknown" | "lane-not-found" | "not-found" => StatusCode::NOT_FOUND, "private-notes-unreachable" | "private-notes-indeterminate" => StatusCode::SERVICE_UNAVAILABLE, "database-busy" | "database-locked" | "message-selectors-not-ready" + | "assistant-grant-authority-not-ready" | "checkpoint-proof-in-progress" | "backup-busy" => StatusCode::SERVICE_UNAVAILABLE, "client-diagnostics-rate-limit" => StatusCode::TOO_MANY_REQUESTS, "read-deadline" => StatusCode::GATEWAY_TIMEOUT, @@ -2010,6 +2012,7 @@ pub fn client_error_code(code: Option<&str>) -> String { | "peer-too-old" | "validation-failed" | "idempotency-conflict" + | "grant-profile-conflict" | "invalid-answer" | "not-answerable" | "idempotency-key-expired" @@ -2058,6 +2061,7 @@ pub fn client_error_code(code: Option<&str>) -> String { | "mission-list-not-ready" | "mission-list-ended" | "message-selectors-not-ready" + | "assistant-grant-authority-not-ready" | "response-too-large" | "runtime-not-local" | "runtime-authority-indeterminate" @@ -9478,6 +9482,38 @@ pub(crate) fn fleet_admission_check( } } +fn pending_assistant_grant_checks( + connection: &rusqlite::Connection, + local_origin: &str, +) -> anyhow::Result> { + let mut statement = connection.prepare_cached( + "SELECT pending.claim_id,pending.kind,pending.origin,pending.actor + FROM assistant_grant_pending pending + WHERE pending.authenticated=0 + AND pending.kind='custom.client.assistant.v1.granted' + AND NOT EXISTS(SELECT 1 FROM assistant_grant_local_appends local + WHERE local.claim_id=pending.claim_id) + ORDER BY pending.claim_id", + )?; + let rows = statement.query_map([], |row| { + Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?, + row.get::<_, String>(2)?, row.get::<_, String>(3)?)) + })?; + rows.map(|row| { + let (id, kind, origin, actor) = row?; + let reason = if origin == local_origin { + "grant predates local-append provenance; re-issue" + } else { + "grant lacks local-append provenance and verified member signature/membership; issuance age unknown" + }; + Ok(DoctorCheck { + name: "assistant-grant-provenance".into(), + status: "warn".into(), + message: format!("{id}: {reason}; kind={kind}; origin={origin}; actor={actor}"), + }) + }).collect() +} + fn doctor_report_within( state: &AppState, clock: &DoctorClock, @@ -9521,6 +9557,9 @@ fn doctor_report_within( message: error.to_string(), }), } + checks.extend(pending_assistant_grant_checks( + &state.store.readers.get(), state.store.origin(), + ).map_err(ApiError::internal)?); Ok(checks) }); checks.check("claim-signatures", || { diff --git a/crates/fractal-api-core/src/api/client_v0/assistant/authorization.rs b/crates/fractal-api-core/src/api/client_v0/assistant/authorization.rs index 805097b453f..5bedafdc672 100644 --- a/crates/fractal-api-core/src/api/client_v0/assistant/authorization.rs +++ b/crates/fractal-api-core/src/api/client_v0/assistant/authorization.rs @@ -122,7 +122,7 @@ pub async fn pin(State(state): State, Extension(session): Extension ApiError { + if error.code == "assistant-grant-subject-not-ready" { + credential_rejected("the client credential is unknown or expired") + } else { + ApiError::bad(error) + } +} + /// Closed authority profiles: callers cannot register a profile or mix its rights. /// Service is reserved and cannot issue credentials or authorize any request. #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -51,6 +59,10 @@ impl Profile { } fn assistant_profile(source: &Value) -> Result<(), ApiError> { + #[cfg(test)] + if tests::SERVICE_PROFILE.get() && Profile::stored(source)? == Profile::Service { + return Ok(()); + } Profile::stored(source)?.issuable() } @@ -64,44 +76,79 @@ fn digest_only(source: &Value) -> Result<(), ApiError> { Ok(()) } -// Issuance-only scan: authentication retains its existing indexed lookup and reads. -// TRANSITIONS serializes completion; several grants of the same profile are allowed. +fn admission_now_ms() -> u128 { + #[cfg(test)] + if let Some(now) = tests::ADMISSION_NOW.get() { + return now; + } + client_now_ms() +} +fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) -> Result, ApiError> { + candidate_grants_except(state, principal, expiry_cut, None, None) +} + +fn candidate_grants_except(state: &AppState, principal: &str, expiry_cut: Option, + excluded: Option<&str>, ignored_profile: Option) -> Result, ApiError> { + let ignored_profile = ignored_profile.map(|profile| match profile { + Profile::Assistant => "assistant", Profile::Service => "service", + }); + authority::candidates(&state.store.readers.get(), principal, owning_person(state)?, + expiry_cut, excluded, ignored_profile).map_err(authority_error)? + .into_iter().map(|grant| { + let profile = Profile::stored(fields(&grant)?)?; + Ok((grant, profile)) + }).collect() +} + +fn unexpired(source: &Value, now: u64) -> bool { + source["expires_at_unix_ms"].as_u64().is_some_and(|expires| expires > now) +} + + +fn witness(grant: &ClaimRecord, profile: Profile) -> Value { + json!({"grant_id":fields(grant).ok().and_then(|source| source.get("grant_id")), + "origin":grant.origin,"profile":match profile { Profile::Assistant => "assistant", Profile::Service => "service" }}) +} + +fn conflict_error() -> ApiError { + ApiError { + status: StatusCode::CONFLICT, + code: "grant-profile-conflict".into(), + message: "principal has active grants of opposite profiles; revoke one to clear the conflict".into(), + details: Box::default(), + } +} + +#[cfg(test)] +pub fn profile_conflict(state: &AppState, granted: &ClaimRecord) -> Result, ApiError> { + profile_conflict_at(state, granted, client_now_ms() as u64) +} + +fn profile_conflict_at(state: &AppState, granted: &ClaimRecord, now: u64) -> Result, ApiError> { + let active = candidate_grants(state, principal(fields(granted)?)?, Some(now))?; + let Some((grant, profile)) = active.iter().find(|(grant, _)| grant.id == granted.id) else { + return Ok(None); + }; + Ok(active.iter().find(|(_, other)| other != profile).map(|(other, other_profile)| + json!({"grants":[witness(grant, *profile),witness(other, *other_profile)]}))) +} + fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { let profile = Profile::stored(source)?; - let principal = principal(source)?; - let ids = { - let connection = state.store.readers.get(); - let mut query = connection.prepare( - "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2" - ).map_err(ApiError::internal)?; - query.query_map(rusqlite::params![GRANTED, principal], |row| row.get::<_, String>(0)) - .map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? - }; - for id in ids { - let grant = state.store.claim_by_id(&id).map_err(ApiError::internal)? - .ok_or_else(|| forbidden("external grant is absent"))?; - if grant.origin != state.store.origin() || grant.actor.as_deref() != Some(owning_person(state)?) - || latest(state, &grant.subject, REVOKED)?.is_some() { - continue; - } - let policy = effective(state, &grant)?; - let active = fields(&policy)?; - if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > client_now_ms() { - profile.compatible(Profile::stored(fields(&grant)?)?)?; - profile.compatible(Profile::stored(active)?)?; + for (_, other) in candidate_grants(state, principal(source)?, Some(admission_now_ms() as u64))? { + if profile != other { + return Err(conflict_error()); } } Ok(()) } pub fn principal(source: &Value) -> Result<&str, ApiError> { - crate::store::assistant_write::principal(source) + authority::principal(source) .ok_or_else(|| forbidden("invalid assistant principal")) } pub const BEGUN: &str = "custom.client.assistant.v1.begun"; -pub const GRANTED: &str = "custom.client.assistant.v1.granted"; -pub const POLICY: &str = "custom.client.assistant.v1.policy"; -pub const REVOKED: &str = "custom.client.assistant.v1.revoked"; +pub use authority::{GRANTED, POLICY, REVOKED}; pub const SCOPES: &[&str] = &[ "read.assistant.summary", "read.assistant.attention", "read.assistant.missions", "read.assistant.agents", "read.assistant.conversation", "read.assistant.terminal", @@ -111,6 +158,10 @@ pub const SCOPES: &[&str] = &[ // against concurrent writers in the authoritative store. pub static TRANSITIONS: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(()); +// Synchronous because append never awaits. Callers may already hold TRANSITIONS: +// always acquire that outer lifecycle lock first, never from inside admission. +static ADMISSIONS: std::sync::Mutex<()> = std::sync::Mutex::new(()); + pub fn owning_person(state: &AppState) -> Result<&str, ApiError> { state.owning_person.as_deref() .filter(|person| person.starts_with("person/") && person.matches('/').count() == 1 && person.len() > 7) @@ -135,13 +186,37 @@ pub fn fields(claim: &ClaimRecord) -> Result<&Value, ApiError> { claim.body.get("fields").ok_or_else(|| forbidden("invalid assistant grant claim")) } pub fn latest(state: &AppState, subject: &str, kind: &str) -> Result, ApiError> { + if matches!(kind, GRANTED | POLICY | REVOKED) { + return authority::latest(&state.store.readers.get(), subject, kind).map_err(authority_error); + } Ok(state.store.claims_for_subject_kind_at(subject, kind, None, true, 1) .map_err(ApiError::internal)?.claims.into_iter().next()) } pub fn append(state: &AppState, subject: String, kind: &str, actor: &str, value: Value, previous: Option<&ClaimRecord>) -> Result { + // Subject fences do not serialize grants on independent subjects for one + // principal. Keep the cross-subject scan and authoritative append indivisible. + let _admission = if kind == GRANTED { + Some(ADMISSIONS.lock().map_err(|_| ApiError::internal("external grant admission lock poisoned"))?) + } else { + None + }; if matches!(kind, BEGUN | GRANTED | POLICY | REVOKED) { - assistant_profile(&value)?; + if kind == REVOKED { + Profile::stored(&value)?; + let granted = authority::latest(&state.store.readers.get(), &subject, GRANTED) + .map_err(authority_error)?.ok_or_else(|| forbidden("assistant grant is absent"))?; + if actor != owning_person(state)? || granted.actor.as_deref() != Some(actor) + || granted.origin != state.store.origin() + || previous.is_none() + || principal(&value)? != principal(fields(&granted)?)? + || ["grant_id", "issuer", "profile"].iter() + .any(|key| value.get(*key) != granted.body["fields"].get(*key)) { + return Err(forbidden("assistant revocation requires the authoritative grant owner and immutable identity")); + } + } else { + assistant_profile(&value)?; + } digest_only(&value)?; if let Some(previous) = previous { let previous = fields(previous)?; @@ -151,11 +226,17 @@ pub fn append(state: &AppState, subject: String, kind: &str, actor: &str, admit_profile(state, &value)?; } } + // Authority/evidence uses the validated policy; fencing uses the real head. + let expected_subject = if matches!(kind, POLICY | REVOKED) { + state.store.latest_claim(&subject, None).map_err(ApiError::internal)?.map(|claim| claim.id) + } else { + previous.map(|claim| claim.id.clone()) + }; state.store.append_claim(&ClaimInput { subject, kind: kind.into(), actor: Some(actor.into()), fields: serde_json::from_value(value).map_err(ApiError::internal)?, evidence: previous.map(|claim| vec![claim.id.clone()]).unwrap_or_default(), - expected_subject: Some(previous.map(|claim| claim.id.clone())), + expected_subject: Some(expected_subject), idempotency_key: None, }).map_err(ApiError::bad) } @@ -168,7 +249,9 @@ pub fn audit(state: &AppState, operation: &str, actor: &str, transport: &str, let mut audit_principal = actor.split_once("/session/").map(|(principal, _)| principal.to_owned()); if let Some(subject) = grant_id.and_then(|id| subject(id).ok()) { for kind in [BEGUN, GRANTED, POLICY, REVOKED] { - if let Some(claim) = latest(state, &subject, kind)? { + // Audit references retained evidence, including unauthoritative overlays. + if let Some(claim) = state.store.claims_for_subject_kind_at(&subject, kind, None, true, 1) + .map_err(ApiError::internal)?.claims.into_iter().next() { audit_principal = Some(principal(fields(&claim)?)?.to_owned()); referenced.push(claim.id); } @@ -188,8 +271,16 @@ pub fn audit(state: &AppState, operation: &str, actor: &str, transport: &str, Ok(()) } +fn transition(state: &AppState, granted: &ClaimRecord, kind: &str) -> Result, ApiError> { + authority::transition(&state.store.readers.get(), granted, kind).map_err(authority_error) +} + +pub fn revoked(state: &AppState, granted: &ClaimRecord) -> Result { + Ok(transition(state, granted, REVOKED)?.is_some()) +} + pub fn effective(state: &AppState, granted: &ClaimRecord) -> Result { - Ok(latest(state, &granted.subject, POLICY)?.unwrap_or_else(|| granted.clone())) + Ok(transition(state, granted, POLICY)?.unwrap_or_else(|| granted.clone())) } pub fn projection(state: &AppState, granted: &ClaimRecord) -> Result { let policy = effective(state, granted)?; @@ -197,7 +288,7 @@ pub fn projection(state: &AppState, granted: &ClaimRecord) -> Result Result Result { + let mut value = projection(state, granted)?; + let policy = effective(state, granted)?; + let source = fields(&policy)?; + let now = client_now_ms() as u64; + value["conflict"] = profile_conflict_at(state, granted, now)?.unwrap_or(Value::Null); + if value["conflict"].is_null() { + let profile = Profile::stored(fields(granted)?)?; + let mut cleared = Vec::new(); + for (other, other_profile) in candidate_grants(state, principal(source)?, None)? { + if profile == other_profile { continue; } + // Historical explanations are optional: another subject's pending proof + // must not turn inspection of this clean grant into a bearer denial. + let explanation = (|| { + let connection = state.store.readers.get(); + let policy = authority::transition(&connection, &other, POLICY)? + .unwrap_or_else(|| other.clone()); + let revoked = authority::transition(&connection, &other, REVOKED)?.is_some(); + Ok::<_, FractalError>((policy, revoked)) + })(); + let (policy, other_revoked) = match explanation { + Err(error) if error.code == "assistant-grant-subject-not-ready" => continue, + result => result.map_err(authority_error)?, + }; + let cause = if other_revoked || value["revoked"] == true { Some("revoked") } + else if !unexpired(fields(&policy)?, now) || !unexpired(source, now) { Some("expired") } else { None }; + if let Some(cause) = cause { + cleared.push(json!({"grants":[witness(granted, profile),witness(&other, other_profile)],"cause":cause})); + } + } + value["cleared_conflicts"] = json!(cleared); + } + Ok(value) +} + pub fn authenticate(state: &AppState, digest: &str, transport: &'static str) -> Result, ApiError> { - let id: Option = state.store.readers.get().query_row( - "SELECT id FROM claims WHERE kind=?1 AND json_extract(body,'$.fields.credential_hash')=?2 ORDER BY store_index DESC LIMIT 1", - rusqlite::params![GRANTED, digest], |row| row.get(0)) - .optional().map_err(ApiError::internal)?; - let Some(id) = id else { return Ok(None) }; - let granted = state.store.claim_by_id(&id).map_err(ApiError::internal)? - .ok_or_else(|| forbidden("assistant grant is absent"))?; + let Some(granted) = authority::by_credential(&state.store.readers.get(), digest) + .map_err(authority_error)? else { return Ok(None); }; session(state, &granted, transport).map(Some) } pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) -> Result { + if !authority::contains(&state.store.readers.get(), &granted.id).map_err(authority_error)? { + return Err(credential_rejected("the client credential is unknown or expired")); + } + let now = client_now_ms() as u64; let policy = effective(state, granted)?; + let is_revoked = revoked(state, granted)?; + if !is_revoked && unexpired(fields(&policy)?, now) + && authority::structurally_valid(granted, &policy) { + let profile = Profile::stored(fields(granted)?)?; + if candidate_grants_except(state, principal(fields(granted)?)?, Some(now), Some(&granted.id), Some(profile))? + .iter().any(|(_, other)| *other != profile) { + return Err(conflict_error()); + } + } let source = fields(&policy)?; let principal = principal(source)?; let granted_fields = fields(granted)?; assistant_profile(granted_fields)?; assistant_profile(source)?; - if self::principal(granted_fields)? != principal - || ["grant_id", "session_actor", "issuer"].iter().any(|key| source[*key] != granted_fields[*key]) - || source["session_actor"].as_str().and_then(|actor| actor.strip_prefix(principal)) - .and_then(|suffix| suffix.strip_prefix("/session/")) != source["grant_id"].as_str() { + if !authority::structurally_valid(granted, &policy) { return Err(forbidden("assistant grant principal and session are inconsistent")); } if granted.origin != state.store.origin() || policy.origin != granted.origin || granted.actor.as_deref() != Some(owning_person(state)?) || policy.actor.as_deref() != Some(owning_person(state)?) { return Err(forbidden("assistant requests require the authoritative grant issuer")); } - if latest(state, &granted.subject, REVOKED)?.is_some() - || source["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) <= client_now_ms() - || source["issuer"] != owning_person(state)? - || !matches!(source["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) || source["disclosure_consent"] != true { + if is_revoked + || !unexpired(source, now) { return Err(forbidden("assistant grant was revoked, expired, or has invalid policy")); } let scopes = source["scopes"].as_array().ok_or_else(|| forbidden("assistant scopes absent"))? @@ -273,23 +402,321 @@ pub fn authorize_route(session: &ClientSession, request: &Request) -> Resu Ok(()) } +#[cfg(test)] +mod conflict_tests; + #[cfg(test)] mod tests { use super::*; + // Only the current fixture thread can exercise the reserved profile through + // the real mutation/session boundary. Production issuable() stays closed. + thread_local! { + pub(super) static SERVICE_PROFILE: std::cell::Cell = const { std::cell::Cell::new(false) }; + pub(super) static ADMISSION_NOW: std::cell::Cell> = const { std::cell::Cell::new(None) }; + } + + fn concurrent_grants(profiles: [&str; 2]) -> (usize, usize) { + let root = tempfile::tempdir().unwrap(); + let mut state = crate::api::tests_shared::state(root.path()); + state.owning_person = Some("person/owner".into()); + let barrier = std::sync::Barrier::new(2); + let results = std::thread::scope(|scope| { + let handles = profiles.into_iter().enumerate().map(|(index, profile)| { + let state = &state; + let barrier = &barrier; + scope.spawn(move || { + SERVICE_PROFILE.set(true); + let id = if index == 0 { "111111111111111111111111" } else { "222222222222222222222222" }; + let source = json!({"profile":profile,"grant_id":id,"principal":PRINCIPAL, + "issuer":"person/owner","session_actor":format!("{PRINCIPAL}/session/{id}"), + "expires_at_unix_ms":u64::MAX,"minimal_read_mode":"approval-once", + "disclosure_consent":true,"scopes":["read.assistant.summary"], + "credential_hash":credential_digest(id)}); + let subject = subject(id).unwrap(); + let begun = append(state, subject.clone(), BEGUN, "person/owner", source.clone(), None).unwrap(); + barrier.wait(); + append(state, subject, GRANTED, "person/owner", source, Some(&begun)) + }) + }).collect::>(); + handles.into_iter().map(|handle| handle.join().unwrap()).collect::>() + }); + let admitted = results.iter().filter(|result| result.is_ok()).count(); + let usable = std::thread::spawn(move || { + SERVICE_PROFILE.set(true); + results.iter().filter_map(|result| result.as_ref().ok()) + .filter(|grant| session(&state, grant, "http").is_ok()).count() + }).join().unwrap(); + (admitted, usable) + } + + // Independent raw-history oracle. Intentionally does not call the projection's + // validator: original identity/digests and effective policy rights have distinct roles. + fn reference_structure(state: &AppState, grant: &ClaimRecord, policy: &ClaimRecord) -> bool { + let Some(original) = grant.body.get("fields").filter(|value| value.is_object()) else { return false }; + let Some(effective) = policy.body.get("fields").filter(|value| value.is_object()) else { return false }; + let parse_principal = |source: &Value| match source.get("principal") { + None => Some(PRINCIPAL), + Some(Value::String(value)) if value == PRINCIPAL => Some(PRINCIPAL), + Some(Value::String(value)) if value == MCP_PRINCIPAL => Some(MCP_PRINCIPAL), + _ => None, + }; + let valid = |claim: &ClaimRecord, source: &Value| { + let Some(principal) = parse_principal(source) else { return false }; + let Some(id) = source["grant_id"].as_str() else { return false }; + subject(id).is_ok_and(|subject| subject == claim.subject) + && claim.actor.as_deref() == state.owning_person.as_deref() + && source["issuer"].as_str() == state.owning_person.as_deref() + && source["session_actor"].as_str() == Some(format!("{principal}/session/{id}").as_str()) + && matches!(source.get("profile"), None | Some(Value::String(_))) + && source.get("profile").is_none_or(|value| value == "assistant" || value == "service") + && !["credential", "code"].iter().any(|key| source.get(*key).is_some()) + && ["credential_hash", "code_hash"].iter().all(|key| source.get(*key).is_none_or(|value| + value.as_str().is_some_and(|digest| digest.len() == 64 + && digest.bytes().all(|byte| byte.is_ascii_hexdigit())))) + }; + grant.origin == policy.origin && grant.subject == policy.subject + && valid(grant, original) && valid(policy, effective) + && matches!(effective["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) + && effective["disclosure_consent"] == true + && effective["expires_at_unix_ms"].as_u64().is_some() + && effective["scopes"].as_array().is_some_and(|scopes| + scopes.iter().all(|scope| scope.as_str().is_some_and(|scope| SCOPES.contains(&scope)))) + && original["credential_hash"].as_str().is_some() + && parse_principal(original) == parse_principal(effective) + && ["grant_id", "session_actor", "issuer", "profile"].iter() + .all(|key| original.get(*key) == effective.get(*key)) + } + + // Deliberately walk subject history rather than reuse the production SQL + // transition selector, effective-policy fold, or revocation helper. + pub(super) fn reference_transition(state: &AppState, grant: &ClaimRecord, kind: &str) + -> Result, ApiError> { + let original = fields(grant)?; + let mut history = state.store.claims_for(&grant.subject, Some(kind)).map_err(ApiError::internal)?; + history.sort_by_key(|claim| std::cmp::Reverse(claim.store_index)); + for claim in history { + let Ok(source) = fields(&claim) else { continue }; + if claim.origin != grant.origin || claim.actor.as_deref() != Some(owning_person(state)?) + || source["issuer"] != owning_person(state)? + || source["grant_id"] != original["grant_id"] + || source["issuer"] != original["issuer"] + || principal(source).ok() != principal(original).ok() + || principal(source).is_err() + || Profile::stored(source).ok() != Profile::stored(original).ok() + || Profile::stored(source).is_err() { + continue; + } + if kind == POLICY && !reference_structure(state, grant, &claim) { + continue; + } + if grant.origin != state.store.origin() + && !state.store.claim_has_authenticated_member_writer(&claim.id).map_err(ApiError::internal)? { + continue; + } + return Ok(Some(claim)); + } + Ok(None) + } + + // Independent Rust-only candidate scan: C's authenticated transition and + // typed-conflict semantics, without the production SQL active prefilter. + pub(super) fn rust_only_admission(state: &AppState, source: &Value) -> Result<(), ApiError> { + let profile = Profile::stored(source)?; + let principal = principal(source)?; + owning_person(state)?; + let ids = { + let connection = state.store.readers.get(); + let mut query = connection.prepare( + "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2" + ).map_err(ApiError::internal)?; + query.query_map(rusqlite::params![GRANTED, principal], |row| row.get::<_, String>(0)) + .map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? + }; + for id in ids { + let grant = state.store.claim_by_id(&id).map_err(ApiError::internal)? + .ok_or_else(|| forbidden("external grant is absent"))?; + if grant.actor.as_deref() != Some(owning_person(state)?) + || (grant.origin != state.store.origin() + && !state.store.claim_has_authenticated_member_writer(&grant.id).map_err(ApiError::internal)?) + || reference_transition(state, &grant, REVOKED)?.is_some() { + continue; + } + let policy = reference_transition(state, &grant, POLICY)?.unwrap_or_else(|| grant.clone()); + if !reference_structure(state, &grant, &policy) { continue; } + let active = fields(&policy)?; + if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > admission_now_ms() { + Profile::stored(fields(&grant)?)?.compatible(Profile::stored(active)?)?; + if profile != Profile::stored(active)? { + return Err(conflict_error()); + } + } + } + Ok(()) + } + + #[test] + fn prefiltered_admission_matches_rust_only_reference() { + struct Clock; + impl Drop for Clock { + fn drop(&mut self) { ADMISSION_NOW.set(None); } + } + ADMISSION_NOW.set(Some(100)); + let _clock = Clock; + let cases = [ + ("live", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), + ("expired", json!({"expires_at_unix_ms":99}), vec![], 0, false, false), + ("equal-boundary", json!({"expires_at_unix_ms":100}), vec![], 0, false, false), + ("null-expiry", json!({"expires_at_unix_ms":null}), vec![], 0, false, false), + ("missing-expiry", json!({}), vec![], 0, false, false), + ("replicated-revoke", json!({"expires_at_unix_ms":101}), vec![], 1, true, true), + ("revoke-of-revoke", json!({"expires_at_unix_ms":101}), vec![], 2, false, false), + ("several-policies-live", json!({"expires_at_unix_ms":99}), vec![102, 98, 101], 0, false, true), + ("several-policies-expired", json!({"expires_at_unix_ms":101}), vec![99, 102, 100], 0, false, false), + ("renewed-expired-base", json!({"expires_at_unix_ms":99}), vec![98, 100, 102], 0, false, true), + ("shortened-long-policy", json!({"expires_at_unix_ms":99}), vec![1000, 99], 0, false, false), + ("wrong-origin-future-policy", json!({"expires_at_unix_ms":99}), vec![98, 99], 0, false, false), + ("unrelated-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, false), + ("legacy-default-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), + ("null-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, false), + ("mcp-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), + ]; + for (name, mut source, policies, revokes, replicated, denied) in cases { + let root = tempfile::tempdir().unwrap(); + let mut state = crate::api::tests_shared::state(root.path()); + state.owning_person = Some("person/owner".into()); + source["profile"] = json!("service"); + if name == "null-principal" { + source["principal"] = Value::Null; + } else if name != "legacy-default-principal" { + source["principal"] = json!(if matches!(name, "unrelated-principal" | "mcp-principal") { MCP_PRINCIPAL } else { PRINCIPAL }); + } + let id = "0123456789abcdef01234567"; + let subject = subject(id).unwrap(); + source["grant_id"] = json!(id); + source["issuer"] = json!("person/owner"); + source["session_actor"] = json!(format!("{}/session/{id}", if name == "mcp-principal" || name == "unrelated-principal" { MCP_PRINCIPAL } else { PRINCIPAL })); + source["minimal_read_mode"] = json!("approval-once"); + source["disclosure_consent"] = json!(true); + source["credential_hash"] = json!("a".repeat(64)); + source["scopes"] = json!([]); + let append_fixture = |store: &Store, kind: &str, value: Value, previous: Option<&ClaimRecord>| { + store.append_claim(&ClaimInput { + subject:subject.clone(), kind:kind.into(), actor:Some("person/owner".into()), + fields:serde_json::from_value(value).unwrap(), + evidence:previous.map(|claim| vec![claim.id.clone()]).unwrap_or_default(), + expected_subject:None, idempotency_key:None, + }).unwrap() + }; + let mut previous = append_fixture(&state.store, GRANTED, source.clone(), None); + for expiry in policies { + let mut policy = source.clone(); + policy["expires_at_unix_ms"] = json!(expiry); + previous = append_fixture(&state.store, POLICY, policy, Some(&previous)); + } + if name == "wrong-origin-future-policy" { + let peer = Store::open_memory("overlay").unwrap(); + let mut forged = source.clone(); + forged["expires_at_unix_ms"] = json!(u64::MAX); + append_fixture(&peer, POLICY, forged, None); + state.store.import_replication("overlay", &peer.export_replication(0).unwrap()).unwrap(); + } + if replicated { + let peer = Store::open_memory("peer").unwrap(); + let revoke = append_fixture(&peer, REVOKED, source.clone(), None); + state.store.import_replication("peer", &peer.export_replication(0).unwrap()).unwrap(); + let imported = state.store.claim_by_id(&revoke.id).map_err(ApiError::internal).unwrap().unwrap(); + assert_eq!(imported.id, revoke.id); + assert_eq!(imported.origin, "peer"); + } else { + for _ in 0..revokes { + // The second revoke cites the first revoke, not the grant: + // neither reader may interpret that as restoring authority. + previous = append_fixture(&state.store, REVOKED, source.clone(), Some(&previous)); + } + } + for owner in [Some("person/owner"), None] { + state.owning_person = owner.map(str::to_owned); + for profile in ["assistant", "service"] { + let principal = if name == "mcp-principal" { MCP_PRINCIPAL } else { PRINCIPAL }; + let candidate = json!({"profile":profile,"principal":principal}); + let old = rust_only_admission(&state, &candidate).map_err(|error| error.code); + let new = admit_profile(&state, &candidate).map_err(|error| error.code); + assert_eq!(new, old, "{name}: owner={owner:?}, profile={profile}"); + if owner.is_some() { + assert_eq!(new.is_err(), denied && profile == "assistant", "{name}: expected decision"); + } + } + } + } + } + + #[test] + fn projection_candidates_apply_effective_expiry_including_repaired_original_expiry() { + for (expiry, policy_expiry, included) in [ + (json!(99), None, false), (json!(101), None, true), + (json!(100), None, false), (json!(u64::MAX), None, true), + (json!(-1), None, false), (json!("101"), None, false), + (json!(101.0), None, false), (Value::Null, None, false), + (json!(99), Some(101), true), (json!(101), Some(99), false), + (Value::Null, Some(101), true), + ] { + let root = tempfile::tempdir().unwrap(); + let mut state = crate::api::tests_shared::state(root.path()); + state.owning_person = Some("person/owner".into()); + let id = "0123456789abcdef01234567"; + let subject = subject(id).unwrap(); + let mut source = json!({"grant_id":id,"issuer":"person/owner", + "session_actor":format!("{PRINCIPAL}/session/{id}"), + "credential_hash":"a".repeat(64),"minimal_read_mode":"approval-once", + "disclosure_consent":true,"scopes":[],"expires_at_unix_ms":expiry}); + let append = |kind: &str, source: Value| state.store.append_claim(&ClaimInput { + subject:subject.clone(),kind:kind.into(),actor:Some("person/owner".into()), + fields:serde_json::from_value(source).unwrap(),evidence:Vec::new(), + expected_subject:None,idempotency_key:None, + }).unwrap(); + let granted = append(GRANTED, source.clone()); + if let Some(expiry) = policy_expiry { + source["expires_at_unix_ms"] = json!(expiry); + append(POLICY, source); + } + let candidates = candidate_grants(&state, PRINCIPAL, Some(100)).unwrap(); + assert_eq!(candidates.iter().any(|(claim, _)| claim.id == granted.id), included); + } + } + + #[test] + fn concurrent_opposite_profiles_have_exactly_one_usable_grant() { + assert_eq!(concurrent_grants(["assistant", "service"]), (1, 1)); + } + + #[test] + fn concurrent_same_profile_grants_remain_usable() { + assert_eq!(concurrent_grants(["assistant", "assistant"]), (2, 2)); + assert_eq!(concurrent_grants(["service", "service"]), (2, 2)); + } + #[test] fn persisted_active_profiles_are_checked_at_grant_admission() { let root = tempfile::tempdir().unwrap(); let mut state = crate::api::tests_shared::state(root.path()); state.owning_person = Some("person/owner".into()); - let source = json!({"principal":PRINCIPAL,"issuer":"person/owner", - "expires_at_unix_ms":u64::MAX,"credential_hash":credential_digest("private bearer")}); + let mut source = json!({"principal":PRINCIPAL,"issuer":"person/owner", + "expires_at_unix_ms":u64::MAX,"credential_hash":credential_digest("private bearer"), + "minimal_read_mode":"approval-once","disclosure_consent":true,"scopes":[]}); for id in ["111111111111111111111111", "222222222222222222222222"] { + source["grant_id"] = json!(id); + source["session_actor"] = json!(format!("{PRINCIPAL}/session/{id}")); append(&state, subject(id).unwrap(), GRANTED, "person/owner", source.clone(), None).unwrap(); } let service_subject = subject("333333333333333333333333").unwrap(); let mut service = source.clone(); service["profile"] = json!("service"); + service["grant_id"] = json!("333333333333333333333333"); + service["session_actor"] = json!(format!("{PRINCIPAL}/session/333333333333333333333333")); + service["minimal_read_mode"] = json!("approval-once"); + service["disclosure_consent"] = json!(true); + service["scopes"] = json!([]); // Simulate an existing profile record without enabling service issuance. let grant = state.store.append_claim(&ClaimInput { subject: service_subject.clone(), kind: GRANTED.into(), actor: Some("person/owner".into()), @@ -297,13 +724,22 @@ mod tests { expected_subject: Some(None), idempotency_key: None, }).unwrap(); let next = subject("444444444444444444444444").unwrap(); + source["grant_id"] = json!("444444444444444444444444"); + source["session_actor"] = json!(format!("{PRINCIPAL}/session/444444444444444444444444")); assert!(append(&state, next.clone(), GRANTED, "person/owner", source.clone(), None).is_err()); assert!(latest(&state, &next, GRANTED).unwrap().is_none()); - state.store.append_claim(&ClaimInput { - subject: service_subject, kind: REVOKED.into(), actor: Some("person/owner".into()), - fields: BTreeMap::new(), evidence: vec![grant.id.clone()], - expected_subject: Some(Some(grant.id)), idempotency_key: None, - }).unwrap(); + let mut forged = fields(&grant).unwrap().clone(); + forged["profile"] = json!("assistant"); + assert!(append(&state, service_subject.clone(), REVOKED, "person/owner", + forged, Some(&grant)).is_err()); + assert!(append(&state, service_subject.clone(), REVOKED, "person/other", + fields(&grant).unwrap().clone(), Some(&grant)).is_err()); + append(&state, service_subject, REVOKED, "person/owner", + fields(&grant).unwrap().clone(), Some(&grant)).unwrap(); + let candidates = candidate_grants(&state, PRINCIPAL, Some(client_now_ms() as u64)).unwrap() + .into_iter().map(|(grant, _)| grant.id).collect::>(); + assert_eq!(candidates.len(), 2); + assert!(!candidates.contains(&grant.id), "revoked history must not reach the admission loop"); assert!(append(&state, next, GRANTED, "person/owner", source, None).is_ok()); } @@ -363,7 +799,7 @@ mod tests { fields:serde_json::from_value(source).unwrap(), evidence:vec![granted.id.clone()], expected_subject:Some(Some(granted.id)), idempotency_key:None, }).unwrap(); - assert!(authenticate(&state, &credential_digest(&id), "unix").is_err()); + assert!(!matches!(authenticate(&state, &credential_digest(&id), "unix"), Ok(Some(_)))); } } diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs new file mode 100644 index 00000000000..2d76102b27a --- /dev/null +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -0,0 +1,685 @@ +use super::*; +use fractal_client::ErrorCode; +use smallclaims::fleet::MemberKey; +use std::collections::BTreeSet; +use std::sync::Arc; + +const FLEET: &str = "86700000-0000-4000-8000-000000000001"; +const OWNER: &str = "person/owner"; +const ASSISTANT_ID: &str = "111111111111111111111111"; +const SERVICE_ID: &str = "222222222222222222222222"; + +// This override is thread-local: the reserved service profile remains closed in +// production, and another test thread cannot accidentally inherit the fixture. +struct ServiceFixture; +impl ServiceFixture { + fn enable() -> Self { + assert!(!tests::SERVICE_PROFILE.replace(true)); + Self + } +} +impl Drop for ServiceFixture { + fn drop(&mut self) { + tests::SERVICE_PROFILE.set(false); + } +} + +fn member(root: &std::path::Path, name: &str) -> AppState { + let mut state = crate::api::tests_shared::state(root); + state.store = Arc::new(Store::open_memory(name).unwrap()); + state.node = name.into(); + state.owning_person = Some(OWNER.into()); + state.fleet_id = Some(FLEET.into()); + state.store.bind_fleet(FLEET).unwrap(); + state +} + +fn replicate(from: &AppState, to: &AppState) { + let exchange = from.store.export_replication_exchange_answering( + FLEET, &to.store.replication_inventory().unwrap(), + &to.store.replication_signature_requests().unwrap(), + ).unwrap(); + to.store.receive_replication_exchange(from.store.origin(), FLEET, &exchange).unwrap(); + to.store.validate_replication_backlog().unwrap(); + to.store.project_replication_backlog().unwrap(); + while !to.store.advance_assistant_grant_authority_backfill().unwrap() {} +} + +fn admitted_pair(root: &std::path::Path) -> (AppState, AppState) { + admitted_pair_with_floor(root, 0) +} + +fn admitted_pair_with_floor(root: &std::path::Path, floor: u64) -> (AppState, AppState) { + let a = member(root, "alder"); + let b = member(root, "birch"); + b.store.set_writer_floor(floor).unwrap(); + let anchor = Arc::new(MemberKey::generate().unwrap().0); + let peer = Arc::new(MemberKey::generate().unwrap().0); + for (state, key) in [(&a, &anchor), (&b, &peer)] { + state.store.pin_fleet_anchor(anchor.public()).unwrap(); + state.store.set_member_key(Some(key.clone())).unwrap(); + } + a.store.admit_fleet_anchor(FLEET, anchor.public(), "listening").unwrap(); + raw_claim(&a, "host/birch", "fleet.member-admitted", OWNER, json!({ + "fleet_id":FLEET,"member_key":peer.public(),"via":"invite","mode":"listening", + "writer_floor":floor + })); + replicate(&a, &b); + assert!(matches!(b.store.fleet_membership().unwrap().state("birch"), + smallclaims::fleet::MemberState::Current(_))); + (a, b) +} + +fn grant_fields(id: &str, profile: &str) -> Value { + json!({"profile":profile,"grant_id":id,"principal":PRINCIPAL, + "issuer":OWNER,"session_actor":format!("{PRINCIPAL}/session/{id}"), + "expires_at_unix_ms":u64::MAX,"minimal_read_mode":"approval-once", + "disclosure_consent":true,"scopes":["read.assistant.summary"], + "credential_hash":credential_digest(id)}) +} + +fn issue(state: &AppState, id: &str, profile: &str) -> Result { + let source = grant_fields(id, profile); + let subject = subject(id).unwrap(); + let begun = append(state, subject.clone(), BEGUN, OWNER, source.clone(), None)?; + append(state, subject, GRANTED, OWNER, source, Some(&begun)) +} + +fn raw_claim(state: &AppState, subject: &str, kind: &str, actor: &str, source: Value) -> ClaimRecord { + state.store.append_claim(&ClaimInput { + subject:subject.into(),kind:kind.into(),actor:Some(actor.into()), + fields:serde_json::from_value(source).unwrap(),evidence:Vec::new(), + expected_subject:None,idempotency_key:None, + }).unwrap() +} + +fn authenticate_id(state: &AppState, id: &str) -> Result, ApiError> { + authenticate(state, &credential_digest(id), "http") +} + +fn assert_conflict(error: &ApiError) { + let typed: ErrorCode = serde_json::from_value(json!(error.code)).unwrap(); + assert_eq!(typed, ErrorCode::GrantProfileConflict); + assert_eq!(error.status, StatusCode::CONFLICT); + assert!(error.details.is_empty(), "bearer errors must not expose owner witnesses"); +} + +fn assert_witness(value: &Value) { + let rows = value["grants"].as_array().unwrap(); + assert_eq!(rows.len(), 2); + for (id, origin, profile) in [(ASSISTANT_ID, "alder", "assistant"), + (SERVICE_ID, "birch", "service")] { + assert!(rows.contains(&json!({"grant_id":id,"origin":origin,"profile":profile})), + "missing grant witness: {value}"); + } +} + +#[test] +fn disconnected_opposite_profiles_conflict_on_both_members_and_revocation_recovers() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let assistant = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let service = issue(&b, SERVICE_ID, "service").unwrap(); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + assert!(authenticate_id(&b, SERVICE_ID).unwrap().is_some()); + replicate(&a, &b); + replicate(&b, &a); + for state in [&a, &b] { + for grant in [&assistant, &service] { + assert!(state.store.claim_has_authenticated_member_writer(&grant.id).unwrap()); + let error = authenticate_id(state, fields(grant).unwrap()["grant_id"].as_str().unwrap()) + .expect_err("both credentials must be suspended on either member"); + assert_conflict(&error); + assert_witness(&profile_conflict(state, grant).unwrap().unwrap()); + assert_witness(&projection_with_witness(state, grant).unwrap()["conflict"]); + } + } + append(&b, service.subject.clone(), REVOKED, OWNER, + fields(&service).unwrap().clone(), Some(&service)).unwrap(); + replicate(&b, &a); + for state in [&a, &b] { + for grant in [&assistant, &service] { + assert!(profile_conflict(state, grant).unwrap().is_none()); + assert!(projection_with_witness(state, grant).unwrap()["conflict"].is_null()); + } + assert!(authenticate_id(state, SERVICE_ID).is_err()); + let inspected = projection_with_witness(state, &assistant).unwrap(); + let cleared = inspected["cleared_conflicts"].as_array().unwrap(); + assert_eq!(cleared.len(), 1); + assert_eq!(cleared[0]["cause"], "revoked"); + assert_witness(&cleared[0]); + } + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + let foreign = authenticate_id(&b, ASSISTANT_ID).err().unwrap(); + assert_eq!(foreign.code, "forbidden"); + assert!(foreign.message.contains("authoritative grant issuer")); +} + +#[test] +fn expiry_boundary_clears_conflict_and_disconnected_reissue_recomputes_it() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let assistant = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let service = issue(&b, SERVICE_ID, "service").unwrap(); + // Birch never receives Alder's assistant grant: it remains a disconnected + // issuer even as Alder receives its grants and policy transitions. + replicate(&b, &a); + assert_witness(&profile_conflict(&a, &assistant).unwrap().unwrap()); + + let mut policy = fields(&service).unwrap().clone(); + policy["expires_at_unix_ms"] = json!(100_u64); + append(&b, service.subject.clone(), POLICY, OWNER, policy, Some(&service)).unwrap(); + replicate(&b, &a); + for (now, expected_count, conflicted) in [(99_u64, 2, true), (100, 1, false), (101, 1, false)] { + let candidates = candidate_grants(&a, PRINCIPAL, Some(now)).unwrap(); + assert_eq!(candidates.len(), expected_count, "SQL/Rust expiry boundary at {now}"); + assert_eq!(candidates.iter().any(|(grant, _)| grant.id == service.id), conflicted); + assert_eq!(profile_conflict_at(&a, &assistant, now).unwrap().is_some(), conflicted); + assert_eq!(profile_conflict_at(&a, &service, now).unwrap().is_some(), conflicted); + assert_eq!(unexpired(fields(&effective(&a, &service).unwrap()).unwrap(), now), conflicted); + } + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + let inspected = projection_with_witness(&a, &assistant).unwrap(); + assert!(inspected["conflict"].is_null()); + let cleared = inspected["cleared_conflicts"].as_array().unwrap(); + assert_eq!(cleared.len(), 1); + assert_eq!(cleared[0]["cause"], "expired"); + assert_witness(&cleared[0]); + + let replacement_id = "333333333333333333333333"; + let replacement = issue(&b, replacement_id, "service").unwrap(); + replicate(&b, &a); + let witness = profile_conflict(&a, &assistant).unwrap().unwrap(); + let rows = witness["grants"].as_array().unwrap(); + assert_eq!(rows.len(), 2); + assert!(rows.contains(&json!({"grant_id":ASSISTANT_ID,"origin":"alder","profile":"assistant"}))); + assert!(rows.contains(&json!({"grant_id":replacement_id,"origin":"birch","profile":"service"}))); + assert!(!rows.iter().any(|row| row["grant_id"] == SERVICE_ID)); + assert!(profile_conflict(&a, &service).unwrap().is_none()); + assert!(profile_conflict(&a, &replacement).unwrap().is_some()); + for id in [ASSISTANT_ID, replacement_id] { + assert_conflict(&authenticate_id(&a, id).err().unwrap()); + } + let inspected = projection_with_witness(&a, &assistant).unwrap(); + assert_eq!(inspected["conflict"], witness); + assert!(inspected["cleared_conflicts"].is_null()); +} + +#[test] +fn same_profile_foreign_grants_do_not_conflict_or_authenticate_on_the_wrong_member() { + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let first = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let second = issue(&b, SERVICE_ID, "assistant").unwrap(); + replicate(&a, &b); + replicate(&b, &a); + for state in [&a, &b] { + for grant in [&first, &second] { + assert!(profile_conflict(state, grant).unwrap().is_none()); + } + } + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + assert!(authenticate_id(&b, SERVICE_ID).unwrap().is_some()); + assert_eq!(authenticate_id(&a, SERVICE_ID).err().unwrap().code, "forbidden"); + assert_eq!(authenticate_id(&b, ASSISTANT_ID).err().unwrap().code, "forbidden"); +} + +#[test] +fn admission_refuses_a_known_authenticated_foreign_opposite_profile() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + issue(&b, SERVICE_ID, "service").unwrap(); + replicate(&b, &a); + let error = issue(&a, ASSISTANT_ID, "assistant").err().unwrap(); + assert_conflict(&error); + assert!(latest(&a, &subject(ASSISTANT_ID).unwrap(), GRANTED).unwrap().is_none()); +} + +#[test] +fn malformed_local_owner_actor_grants_cannot_suspend_a_local_credential() { + let root = tempfile::tempdir().unwrap(); + for invalid in ["profile", "grant_id", "principal", "issuer", "session_actor", + "minimal_read_mode", "disclosure_consent", "scopes", "credential_hash"] { + let state = member(root.path(), "alder"); + let local = issue(&state, ASSISTANT_ID, "assistant").unwrap(); + let mut source = grant_fields(SERVICE_ID, "service"); + source[invalid] = Value::Null; + let malformed = raw_claim(&state, &subject(SERVICE_ID).unwrap(), GRANTED, OWNER, source); + assert_eq!(malformed.origin, local.origin); + assert_eq!(malformed.actor.as_deref(), Some(OWNER)); + assert!(profile_conflict(&state, &local).unwrap().is_none(), "{invalid}"); + assert!(authenticate_id(&state, ASSISTANT_ID).unwrap().is_some(), "{invalid}"); + assert!(projection_with_witness(&state, &local).unwrap()["conflict"].is_null(), "{invalid}"); + } +} + +// Same shape as fleet::service_grants' rollback counterexample: a service grant +// with a non-assistant scope (3), an assistant grant (4) and a well-formed service +// grant (7), all active for assistant/chatgpt on one member. +#[test] +fn compat_counterexample_suspends_the_valid_pair_and_refuses_the_malformed_service() { + let root = tempfile::tempdir().unwrap(); + let state = member(root.path(), "issuer"); + let [malformed, assistant, service] = ["000000000000000000000003", + "000000000000000000000004", "000000000000000000000007"]; + let mut source = grant_fields(malformed, "service"); + source["scopes"] = json!(["read.service.status"]); + raw_claim(&state, &subject(malformed).unwrap(), GRANTED, OWNER, source); + issue(&state, assistant, "assistant").unwrap(); + raw_claim(&state, &subject(service).unwrap(), GRANTED, OWNER, grant_fields(service, "service")); + for id in [assistant, service] { + assert_conflict(&authenticate_id(&state, id).expect_err("the valid opposite pair is suspended")); + } + assert!(authenticate_id(&state, malformed).unwrap().is_none(), + "malformed service evidence must not enter bearer authority"); +} + +#[test] +fn malformed_authenticated_foreign_grants_cannot_suspend_a_local_credential() { + let root = tempfile::tempdir().unwrap(); + // Each case is independently a signed admitted writer's claim, rather than + // an unsigned claim rejected before it can exercise the conflict scanner. + for invalid in ["profile", "grant_id", "principal", "issuer", "session_actor", + "minimal_read_mode", "disclosure_consent", "scopes", "credential_hash", "actor"] { + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let mut source = grant_fields(SERVICE_ID, "service"); + if invalid != "actor" { + source[invalid] = Value::Null; + } + let foreign = raw_claim(&b, &subject(SERVICE_ID).unwrap(), GRANTED, + if invalid == "actor" { "person/intruder" } else { OWNER }, source); + replicate(&b, &a); + assert!(a.store.claim_by_id(&foreign.id).unwrap().is_some(), "{invalid}"); + assert!(a.store.claim_has_authenticated_member_writer(&foreign.id).unwrap(), "{invalid}"); + assert!(profile_conflict(&a, &local).unwrap().is_none(), "{invalid}"); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some(), "{invalid}"); + } +} + +#[test] +fn foreign_policy_with_mismatched_identity_cannot_clear_a_conflict() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let foreign = issue(&b, SERVICE_ID, "service").unwrap(); + let mut policy = fields(&foreign).unwrap().clone(); + policy["session_actor"] = json!("assistant/chatgpt/session/333333333333333333333333"); + raw_claim(&b, &foreign.subject, POLICY, OWNER, policy); + replicate(&b, &a); + assert!(profile_conflict(&a, &local).unwrap().is_some()); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID).err().unwrap()); +} + +#[test] +fn wrong_origin_revocation_and_expired_policy_cannot_clear_conflict() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + for kind in [REVOKED, POLICY] { + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let foreign = issue(&b, SERVICE_ID, "service").unwrap(); + replicate(&a, &b); + replicate(&b, &a); + let mut overlay = fields(&foreign).unwrap().clone(); + if kind == POLICY { + overlay["expires_at_unix_ms"] = json!(1_u64); + } + // An admitted, signed writer with an owner-shaped actor still cannot + // mutate another member's grant lifecycle. + let malicious = raw_claim(&a, &foreign.subject, kind, OWNER, overlay); + replicate(&a, &b); + for state in [&a, &b] { + assert!(state.store.claim_has_authenticated_member_writer(&malicious.id).unwrap()); + assert_eq!(effective(state, &foreign).unwrap().id, foreign.id); + assert_witness(&profile_conflict(state, &local).unwrap().unwrap()); + for id in [ASSISTANT_ID, SERVICE_ID] { + assert_conflict(&authenticate_id(state, id).err().unwrap()); + } + let inspected = projection_with_witness(state, &local).unwrap(); + assert!(inspected["conflict"].is_object()); + assert!(inspected["cleared_conflicts"].is_null()); + } + } +} + +#[test] +fn malformed_same_origin_expired_policy_keeps_the_last_valid_live_policy() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let foreign = issue(&b, SERVICE_ID, "service").unwrap(); + let mut live = fields(&foreign).unwrap().clone(); + live["policy_revision"] = json!(2); + let live = append(&b, foreign.subject.clone(), POLICY, OWNER, live, Some(&foreign)).unwrap(); + let mut malformed = fields(&live).unwrap().clone(); + malformed["expires_at_unix_ms"] = json!(1_u64); + malformed["session_actor"] = json!("assistant/chatgpt/session/not-this-grant"); + raw_claim(&b, &foreign.subject, POLICY, OWNER, malformed); + replicate(&a, &b); + replicate(&b, &a); + for state in [&a, &b] { + assert_eq!(effective(state, &foreign).unwrap().id, live.id); + assert_witness(&profile_conflict(state, &local).unwrap().unwrap()); + assert_conflict(&authenticate_id(state, ASSISTANT_ID).err().unwrap()); + } +} + +#[test] +fn unauthenticated_legacy_transitions_preserve_authenticated_lifecycle_history() { + let root = tempfile::tempdir().unwrap(); + for (scenario, kind) in [("renewal", POLICY), ("renewal", REVOKED), + ("narrowing", POLICY), ("revocation", REVOKED)] { + let (a, b) = admitted_pair_with_floor(root.path(), 10); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let mut expired = grant_fields(SERVICE_ID, "service"); + expired["expires_at_unix_ms"] = json!(if scenario == "renewal" { 1_u64 } else { u64::MAX }); + let foreign = raw_claim(&b, &subject(SERVICE_ID).unwrap(), GRANTED, OWNER, expired); + let mut live = fields(&foreign).unwrap().clone(); + live["expires_at_unix_ms"] = json!(if scenario == "narrowing" { 1_u64 } else { u64::MAX }); + let live = raw_claim(&b, &foreign.subject, POLICY, OWNER, live); + let authentic_revoke = (scenario == "revocation").then(|| + raw_claim(&b, &foreign.subject, REVOKED, OWNER, fields(&foreign).unwrap().clone())); + replicate(&b, &a); + assert!(a.store.claim_has_authenticated_member_writer(&foreign.id).unwrap()); + assert!(a.store.claim_has_authenticated_member_writer(&live.id).unwrap()); + if let Some(revoke) = &authentic_revoke { + assert!(a.store.claim_has_authenticated_member_writer(&revoke.id).unwrap()); + } + assert_eq!(effective(&a, &foreign).unwrap().id, live.id); + assert_eq!(revoked(&a, &foreign).unwrap(), scenario == "revocation"); + + // A different incarnation of the same writer sends a signed envelope + // below the admission floor. It is visible Legacy data, not authority, + // even though origin, owner actor and immutable grant identity match. + let legacy = member(root.path(), "birch"); + legacy.store.set_member_key(Some(Arc::new(MemberKey::generate().unwrap().0))).unwrap(); + let mut source = fields(&foreign).unwrap().clone(); + source["expires_at_unix_ms"] = json!(if scenario == "narrowing" { u64::MAX } else { 1_u64 }); + let overlay = raw_claim(&legacy, &foreign.subject, kind, OWNER, source); + replicate(&legacy, &a); + let overlay = a.store.claim_by_id(&overlay.id).unwrap().unwrap(); + let retained = a.store.claim_by_id(&live.id).unwrap().unwrap(); + assert!(overlay.store_index > retained.store_index); + assert_eq!(overlay.origin, foreign.origin); + assert_eq!(overlay.actor, foreign.actor); + let connection = a.store.readers.get(); + let (signatures, sequence): (u64, u64) = connection.query_row( + "SELECT count(*),max(sequence) FROM replica_records JOIN replica_envelope_signatures + USING(writer,sequence,envelope_hash) WHERE claim_id=?1", + [&overlay.id], |row| Ok((row.get(0)?, row.get(1)?))).unwrap(); + assert!(signatures > 0, "this regression must pass the signature-row prefilter"); + drop(connection); + assert!(matches!(a.store.fleet_membership().unwrap().window("birch", sequence), + smallclaims::fleet::Window::Legacy)); + assert!(!a.store.claim_has_authenticated_member_writer(&overlay.id).unwrap()); + assert_eq!(tests::reference_transition(&a, &foreign, POLICY).unwrap().unwrap().id, live.id); + assert_eq!(tests::reference_transition(&a, &foreign, REVOKED).unwrap().map(|claim| claim.id), + authentic_revoke.as_ref().map(|claim| claim.id.clone())); + // Maintenance has finished, but this below-floor incarnation cannot + // authenticate. Its retained transition still fences its own subject; + // it must neither grant bearer access nor replace the last authenticated + // snapshot used for cross-subject conflict admission. + assert!(authenticate_id(&a, SERVICE_ID).unwrap().is_none()); + for error in [ + effective(&a, &foreign).unwrap_err(), + revoked(&a, &foreign).unwrap_err(), + ] { + assert_eq!(error.code, "forbidden"); + assert_eq!(error.details["reason"], "credential-rejected"); + } + let candidate = json!({"profile":"assistant","principal":PRINCIPAL}); + let reference = tests::rust_only_admission(&a, &candidate).map_err(|error| error.code); + let production = admit_profile(&a, &candidate).map_err(|error| error.code); + assert_eq!(production, reference, "{scenario}/{kind}: independent provenance-aware oracle"); + assert_eq!(production.is_err(), scenario == "renewal"); + if scenario == "renewal" { + assert_witness(&profile_conflict(&a, &local).unwrap().unwrap()); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID).expect_err("the old renewal remains active")); + } else { + assert!(profile_conflict(&a, &local).unwrap().is_none()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + } + } +} + +#[test] +fn signed_revocation_arriving_before_its_grant_converges_without_conflict() { + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + replicate(&a, &b); + let source = grant_fields(SERVICE_ID, "service"); + let subject = subject(SERVICE_ID).unwrap(); + // Replicated custom lifecycle claims are open data. Import the authentic + // revocation first, while its grant is absent, then import that grant. + let revoked = raw_claim(&b, &subject, REVOKED, OWNER, source.clone()); + replicate(&b, &a); + assert!(latest(&a, &subject, GRANTED).unwrap().is_none()); + assert!(a.store.claim_by_id(&revoked.id).unwrap().is_some()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + let granted = raw_claim(&b, &subject, GRANTED, OWNER, source); + replicate(&b, &a); + for state in [&a, &b] { + let revoked = state.store.claim_by_id(&revoked.id).unwrap().unwrap(); + let granted = state.store.claim_by_id(&granted.id).unwrap().unwrap(); + assert!(revoked.store_index < granted.store_index); + assert!(state.store.claim_has_authenticated_member_writer(&revoked.id).unwrap()); + assert!(state.store.claim_has_authenticated_member_writer(&granted.id).unwrap()); + assert!(profile_conflict(state, &local).unwrap().is_none()); + assert!(profile_conflict(state, &granted).unwrap().is_none()); + let inspected = projection_with_witness(state, &local).unwrap(); + let cleared = inspected["cleared_conflicts"].as_array().unwrap(); + assert_eq!(cleared.len(), 1); + assert_eq!(cleared[0]["cause"], "revoked"); + assert_witness(&cleared[0]); + } + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); +} + +#[test] +fn unverifiable_foreign_grant_cannot_suspend_a_local_credential() { + let root = tempfile::tempdir().unwrap(); + // Legacy replication projects unsigned envelopes. Mere visibility and an + // owner-shaped actor are not sufficient provenance for a conflict witness. + let a = member(root.path(), "alder"); + let b = member(root.path(), "birch"); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let foreign = raw_claim(&b, &subject(SERVICE_ID).unwrap(), GRANTED, OWNER, + grant_fields(SERVICE_ID, "service")); + replicate(&b, &a); + assert!(a.store.claim_by_id(&foreign.id).unwrap().is_some()); + assert!(!a.store.claim_has_authenticated_member_writer(&foreign.id).unwrap()); + assert!(profile_conflict(&a, &local).unwrap().is_none()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); +} + +#[test] +fn admission_reads_the_authority_projection_index() { + let root = tempfile::tempdir().unwrap(); + let state = member(root.path(), "alder"); + let grant = issue(&state, ASSISTANT_ID, "assistant").unwrap(); + let candidates = candidate_grants(&state, PRINCIPAL, Some(client_now_ms() as u64)).unwrap(); + assert_eq!(candidates.len(), 1); + assert_eq!(candidates[0].0.id, grant.id); + let connection = state.store.readers.get(); + let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-ha14d9df71ca8 owner=fractal_api_core::api::client_v0::external_grants::conflict_tests TODO=trace-statement-and-value-representation */ &format!("EXPLAIN QUERY PLAN {}", authority::CANDIDATES_QUERY)).unwrap(); + let expiry = authority::expiry_key(client_now_ms() as u64); + let plan = query.query_map(rusqlite::params![PRINCIPAL, OWNER, expiry, + Option::<&str>::None, Option::<&str>::None], |row| row.get::<_, String>(3)).unwrap() + .collect::, _>>().unwrap(); + assert!(plan.iter().any(|step| step.contains("assistant_grant_effective_active_index")), + "admission must use the effective authority projection: {plan:?}"); + assert!(plan.iter().all(|step| !step.contains("claims")), + "admission must never scan raw claim history: {plan:?}"); +} + +#[test] +fn p1_policy_candidates_keep_read_acquisitions_bounded_with_expired_history() { + // Profiling is process-global, so isolate it using the profiler's own + // subprocess convention instead of mutating parallel tests' environment. + const CHILD: &str = "FRACTAL_POLICY_CANDIDATE_PROFILE_CHILD"; + if std::env::var_os(CHILD).is_none() { + let directory = tempfile::tempdir().unwrap(); + let status = std::process::Command::new(std::env::current_exe().unwrap()) + .args(["--exact", + "api::client_v0::external_grants::conflict_tests::p1_policy_candidates_keep_read_acquisitions_bounded_with_expired_history", + "--nocapture"]) + .env(CHILD, "1") + .env("ST3_PROFILE_DIR", directory.path()) + .env("ST3_PROFILE_SLOW_MS", "0") + .status().unwrap(); + assert!(status.success(), "isolated policy candidate regression failed"); + let log = std::fs::read_to_string(directory.path().join("slow.jsonl")).unwrap(); + let rows = log.lines().map(|line| serde_json::from_str::(line).unwrap()) + .collect::>(); + let acquisitions = |label: &str| rows.iter().find(|row| row["label"] == label) + .unwrap()["read_acquisitions"].as_u64().unwrap(); + let before = acquisitions("p1-policy-candidates-before"); + let after = acquisitions("p1-policy-candidates-after"); + assert!(before > 0, "the measured scan must acquire real read connections"); + assert_eq!(after, before, "expired policy history and wrong-origin renewals must be pruned before per-grant reads"); + let two = acquisitions("p1-authentication-n2"); + let six = acquisitions("p1-authentication-n6"); + assert!(two > 0, "authentication must acquire real read connections"); + assert_eq!(six, two, "authenticated foreign candidates must use constant-N batched reads"); + return; + } + smallclaims::profile::init_from_env(); + let root = tempfile::tempdir().unwrap(); + let a = member(root.path(), "alder"); + let b = member(root.path(), "birch"); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let measure = |label: &'static str| { + let operation = smallclaims::profile::Op::start(label, None).unwrap(); + { + let _entered = operation.enter(); + let candidates = candidate_grants(&a, PRINCIPAL, Some(100)).unwrap(); + assert_eq!(candidates.len(), 1); + assert_eq!(candidates[0].0.id, local.id); + } + operation.finish(); + }; + measure("p1-policy-candidates-before"); + for index in 0..128 { + let id = format!("{:024x}", index + 1000); + let subject = subject(&id).unwrap(); + let mut expired = grant_fields(&id, "service"); + expired["expires_at_unix_ms"] = json!(1); + raw_claim(&a, &subject, GRANTED, OWNER, expired.clone()); + raw_claim(&a, &subject, POLICY, OWNER, expired.clone()); + // A future policy from another origin must not pull this expired + // issuer grant back into the per-candidate Rust authority fold. + expired["expires_at_unix_ms"] = json!(u64::MAX); + raw_claim(&b, &subject, POLICY, OWNER, expired); + } + replicate(&b, &a); + measure("p1-policy-candidates-after"); + + let (a, b) = admitted_pair(root.path()); + issue(&a, ASSISTANT_ID, "assistant").unwrap(); + for (count, label) in [(1, "p1-authentication-n2"), (5, "p1-authentication-n6")] { + let start = if count == 1 { 0 } else { 1 }; + for index in start..count { + let id = format!("{:024x}", index + 2000); + let source = grant_fields(&id, "service"); + let grant = raw_claim(&b, &subject(&id).unwrap(), GRANTED, OWNER, source.clone()); + raw_claim(&b, &grant.subject, POLICY, OWNER, source); + } + replicate(&b, &a); + let operation = smallclaims::profile::Op::start(label, None).unwrap(); + { + let _entered = operation.enter(); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID) + .expect_err("all measured opposite-profile grants remain active")); + } + operation.finish(); + } +} + +#[test] +fn dirty_grant_reads_and_bearers_fail_closed_without_blocking_an_unrelated_credential() { + let root = tempfile::tempdir().unwrap(); + let state = member(root.path(), "issuer"); + let grant = issue(&state, ASSISTANT_ID, "assistant").unwrap(); + let independent = issue(&state, SERVICE_ID, "assistant").unwrap(); + while !state.store.advance_assistant_grant_authority_backfill().unwrap() {} + authenticate_id(&state, ASSISTANT_ID).unwrap().unwrap(); + authenticate_id(&state, SERVICE_ID).unwrap().unwrap(); + state.store.connection.write().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&grant.id], + ).unwrap(); + assert!(authenticate_id(&state, ASSISTANT_ID).unwrap().is_none()); + authenticate_id(&state, SERVICE_ID).unwrap().unwrap(); + let denied = credential_rejected("the client credential is unknown or expired"); + for error in [ + session(&state, &grant, "http").unwrap_err(), + effective(&state, &grant).unwrap_err(), + revoked(&state, &grant).unwrap_err(), + projection(&state, &grant).unwrap_err(), + latest(&state, &grant.subject, GRANTED).unwrap_err(), + ] { + assert_eq!(error.status, denied.status); + assert_eq!(error.code, denied.code); + assert_eq!(error.message, denied.message); + assert_eq!(error.details, denied.details); + } + assert_eq!(candidate_grants(&state, PRINCIPAL, Some(0)).unwrap() + .iter().map(|(claim, _)| claim.id.as_str()).collect::>(), + BTreeSet::from([grant.id.as_str(), independent.id.as_str()])); +} + +#[test] +fn dirty_opposite_profile_witness_does_not_clear_an_established_conflict() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let service = issue(&b, SERVICE_ID, "service").unwrap(); + replicate(&a, &b); + replicate(&b, &a); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID).unwrap_err()); + a.store.connection.write().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&service.id], + ).unwrap(); + assert!(authenticate_id(&a, SERVICE_ID).unwrap().is_none(), + "the dirty subject's own credential is fenced"); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID).unwrap_err()); + assert_eq!(candidate_grants(&a, PRINCIPAL, Some(0)).unwrap().len(), 2, + "pending work cannot erase the last authenticated opposite-profile snapshot"); +} + +#[test] +fn clean_grant_inspection_omits_pending_expired_or_revoked_opposite_history() { + let _service = ServiceFixture::enable(); + for cause in ["expired", "revoked"] { + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let assistant = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let service = issue(&b, SERVICE_ID, "service").unwrap(); + let mut source = fields(&service).unwrap().clone(); + let kind = if cause == "expired" { + source["expires_at_unix_ms"] = json!(1_u64); + POLICY + } else { REVOKED }; + append(&b, service.subject.clone(), kind, OWNER, source, Some(&service)).unwrap(); + replicate(&b, &a); + let inspected = projection_with_witness(&a, &assistant).unwrap(); + assert_eq!(inspected["cleared_conflicts"][0]["cause"], cause); + a.store.connection.write().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&service.id], + ).unwrap(); + assert!(authenticate_id(&a, SERVICE_ID).unwrap().is_none()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + let inspected = projection_with_witness(&a, &assistant).unwrap(); + assert!(inspected["conflict"].is_null()); + assert_eq!(inspected["cleared_conflicts"], json!([])); + assert_eq!(inspected["revoked"], false); + assert_eq!(inspected["id"], ASSISTANT_ID); + } +} diff --git a/crates/fractal-api-core/src/api/tests.rs b/crates/fractal-api-core/src/api/tests.rs index 066bb3f51d1..76a987e2b30 100644 --- a/crates/fractal-api-core/src/api/tests.rs +++ b/crates/fractal-api-core/src/api/tests.rs @@ -1044,6 +1044,45 @@ async fn native_session_reports_cannot_replace_a_successor_binding() { assert_eq!(state.store.claims_for(subject, Some("harness.session-file")).unwrap().len(), 2); } +#[test] +fn doctor_lists_unmarked_pending_grants_without_dating_remote_history() { + let store = Store::open_memory("amber").unwrap(); + let connection = store.connection.lock().expect("fixture writer"); + for (id, kind, origin, authenticated) in [ + ("claim/local-a", "custom.client.assistant.v1.granted", "amber", 0), + ("claim/local-b", "custom.client.assistant.v1.granted", "amber", 0), + ("claim/remote", "custom.client.assistant.v1.granted", "birch", 0), + ("claim/verified", "custom.client.assistant.v1.granted", "amber", 1), + ("claim/marked", "custom.client.assistant.v1.granted", "amber", 0), + ("claim/policy", "custom.client.assistant.v1.policy", "amber", 0), + ("claim/revoked", "custom.client.assistant.v1.revoked", "amber", 0), + ] { + connection.execute( + "INSERT INTO assistant_grant_pending + (claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) + VALUES(?1,?1,?2,?3,'person/operator',1,?4,'{}')", + rusqlite::params![id, kind, origin, authenticated], + ).unwrap(); + } + connection.execute( + "INSERT INTO assistant_grant_local_appends(claim_id) VALUES('claim/marked')", [], + ).unwrap(); + let checks = pending_assistant_grant_checks(&connection, "amber").unwrap(); + assert_eq!(checks.len(), 3); + for (check, id) in checks[..2].iter().zip(["claim/local-a", "claim/local-b"]) { + assert_eq!(check.name, "assistant-grant-provenance"); + assert_eq!(check.status, "warn"); + assert_eq!(check.message, format!( + "{id}: grant predates local-append provenance; re-issue; kind=custom.client.assistant.v1.granted; origin=amber; actor=person/operator" + )); + } + assert!(checks[2].message.starts_with("claim/remote: grant lacks local-append provenance")); + assert!(checks[2].message.contains("issuance age unknown")); + assert!(!checks[2].message.contains("predates")); + connection.execute("UPDATE assistant_grant_pending SET authenticated=1", []).unwrap(); + assert!(pending_assistant_grant_checks(&connection, "amber").unwrap().is_empty()); +} + #[test] fn doctor_flags_low_descriptor_limits_and_high_usage() { let low = descriptor_usage_check(256, 8192, Some(92)); diff --git a/crates/fractal-client-codegen/templates/Client.swift.in b/crates/fractal-client-codegen/templates/Client.swift.in index cf0251cacd9..dd2f94a1bf3 100644 --- a/crates/fractal-client-codegen/templates/Client.swift.in +++ b/crates/fractal-client-codegen/templates/Client.swift.in @@ -299,7 +299,7 @@ public actor FractalClient { public func beginPairing(deviceName: String, personID: String) async throws -> Envelope { try await post("v1/client/pairings", PersonPairingBegin(apiVersion: fractalClientAPIVersion, deviceName: deviceName, personID: personID)) } public func beginPairing(_ request: PairingBegin) async throws -> Envelope { try await post("v1/client/pairings", request) } public func completePairing(pairingID: String, code: String, devicePublicKey: String) async throws -> Envelope { try await post("v1/client/pairings/\(pairingID.replacingOccurrences(of: "pairing/", with: ""))/complete", PairingComplete(apiVersion: fractalClientAPIVersion, code: code, devicePublicKey: devicePublicKey)) } - public func assistantGrant(_ id: String) async throws -> Envelope { try await get("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)") } + public func assistantGrant(_ id: String, witness: Bool = false) async throws -> Envelope { try await get("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)", query: witness ? [.init(name: "witness", value: "1")] : []) } public func assistantGrantRevoke(_ id: String) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/revoke", [String: String]()) } public func assistantGrantPolicy(_ id: String, _ policy: AssistantGrantPolicy) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/policy", policy) } public func assistantGrantReadTrust(_ id: String, _ trust: AssistantReadTrustRequest) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/read-trust", trust) } diff --git a/crates/fractal-client-codegen/templates/Client.ts.in b/crates/fractal-client-codegen/templates/Client.ts.in index 54253b63f42..f99b064142e 100644 --- a/crates/fractal-client-codegen/templates/Client.ts.in +++ b/crates/fractal-client-codegen/templates/Client.ts.in @@ -482,8 +482,8 @@ export class FractalClient { return this.request('POST', `/v1/client/pairings/${encodeURIComponent(routedId(id))}/complete`, request, undefined, undefined, requestOptions); } - async assistantGrant(id: string): Promise> { - return this.request('GET', `/v1/client/assistant/grants/${encodeURIComponent(id)}`); + async assistantGrant(id: string, options: { witness?: boolean } = {}): Promise> { + return this.request('GET', `/v1/client/assistant/grants/${encodeURIComponent(id)}${query({ witness: options.witness ? 1 : undefined })}`); } async assistantGrantRevoke(id: string): Promise> { return this.request('POST', `/v1/client/assistant/grants/${encodeURIComponent(id)}/revoke`, {}); diff --git a/crates/fractal-client-codegen/templates/Models.swift.in b/crates/fractal-client-codegen/templates/Models.swift.in index 2d7837069e3..f95035ab8c9 100644 --- a/crates/fractal-client-codegen/templates/Models.swift.in +++ b/crates/fractal-client-codegen/templates/Models.swift.in @@ -153,6 +153,8 @@ public enum ErrorCode: Codable, Sendable, Equatable { case peerTooOld case validationFailed case idempotencyConflict + case grantProfileConflict + case assistantGrantAuthorityNotReady case agentsPublicationRowTooLarge case attentionMigrated case invalidAnswer, notAnswerable @@ -245,6 +247,8 @@ public enum ErrorCode: Codable, Sendable, Equatable { case "peer-too-old": .peerTooOld case "validation-failed": .validationFailed case "idempotency-conflict": .idempotencyConflict + case "grant-profile-conflict": .grantProfileConflict + case "assistant-grant-authority-not-ready": .assistantGrantAuthorityNotReady case "stale-fence": .staleFence case "issuer-required": .issuerRequired case "pairing-origin-required": .pairingOriginRequired @@ -337,6 +341,8 @@ public enum ErrorCode: Codable, Sendable, Equatable { case .peerTooOld: "peer-too-old" case .validationFailed: "validation-failed" case .idempotencyConflict: "idempotency-conflict" + case .grantProfileConflict: "grant-profile-conflict" + case .assistantGrantAuthorityNotReady: "assistant-grant-authority-not-ready" case .staleFence: "stale-fence" case .issuerRequired: "issuer-required" case .pairingOriginRequired: "pairing-origin-required" @@ -1433,7 +1439,21 @@ public struct AssistantGrant: Codable, Sendable { public let kind, id, sessionActor, deviceID, keyID, issuer, expiresAt, consentEvidence: String; public let principal: AssistantPrincipal; public let senderClass: AssistantSenderClass; public let scopes: [AssistantScope]; public let policyRevision: UInt64; public let minimalReadMode: AssistantMinimalReadMode; public let recipientAllowlist: [String]; public let disclosureConsent, revoked: Bool /// Owner-provisioned SCG read pins; absent means every assistant read is denied. public let readTrust: AssistantReadTrust? - enum CodingKeys: String, CodingKey { case kind, id, sessionActor = "session_actor", deviceID = "device_id", keyID = "key_id", issuer, expiresAt = "expires_at", consentEvidence = "consent_evidence", principal, senderClass = "sender_class", scopes, policyRevision = "policy_revision", minimalReadMode = "minimal_read_mode", recipientAllowlist = "recipient_allowlist", disclosureConsent = "disclosure_consent", revoked, readTrust = "read_trust" } + public let conflict: GrantProfileConflictWitness? + public let clearedConflicts: [ClearedGrantProfileConflictWitness]? + enum CodingKeys: String, CodingKey { case kind, id, sessionActor = "session_actor", deviceID = "device_id", keyID = "key_id", issuer, expiresAt = "expires_at", consentEvidence = "consent_evidence", principal, senderClass = "sender_class", scopes, policyRevision = "policy_revision", minimalReadMode = "minimal_read_mode", recipientAllowlist = "recipient_allowlist", disclosureConsent = "disclosure_consent", revoked, readTrust = "read_trust", conflict, clearedConflicts = "cleared_conflicts" } +} +public enum ExternalGrantProfile: String, Codable, Sendable { case assistant, service } +public enum GrantProfileConflictCause: String, Codable, Sendable { case revoked, expired } +public struct GrantProfileWitness: Codable, Sendable { + public let grantID: String?; public let origin: String; public let profile: ExternalGrantProfile + enum CodingKeys: String, CodingKey { case grantID = "grant_id", origin, profile } +} +public struct GrantProfileConflictWitness: Codable, Sendable { + public let grants: [GrantProfileWitness] +} +public struct ClearedGrantProfileConflictWitness: Codable, Sendable { + public let grants: [GrantProfileWitness]; public let cause: GrantProfileConflictCause } public struct AssistantGrantPolicy: Codable, Sendable { public let apiVersion, consentEvidence: String; public let scopes: [AssistantScope]; public let expiresInSeconds: UInt64?; public let disclosureConsent: Bool; public let minimalReadMode: AssistantMinimalReadMode; public let recipientAllowlist: [String]? diff --git a/crates/fractal-client-codegen/templates/generated.rs.in b/crates/fractal-client-codegen/templates/generated.rs.in index 7b5909ae852..195ea6015ff 100644 --- a/crates/fractal-client-codegen/templates/generated.rs.in +++ b/crates/fractal-client-codegen/templates/generated.rs.in @@ -134,6 +134,8 @@ pub enum ErrorCode { PeerTooOld, ValidationFailed, IdempotencyConflict, + GrantProfileConflict, + AssistantGrantAuthorityNotReady, LegacyActionReceiptUntrusted, IssuerRequired, PairingOriginRequired, @@ -4326,6 +4328,40 @@ pub struct AssistantGrant { pub revoked: bool, #[serde(default, skip_serializing_if = "Option::is_none")] pub read_trust: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub conflict: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cleared_conflicts: Option>, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum ExternalGrantProfile { + Assistant, + Service, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum GrantProfileConflictCause { + Revoked, + Expired, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct GrantProfileWitness { + pub grant_id: Option, + pub origin: String, + pub profile: ExternalGrantProfile, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct GrantProfileConflictWitness { + pub grants: Vec, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct ClearedGrantProfileConflictWitness { + pub grants: Vec, + pub cause: GrantProfileConflictCause, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[serde(deny_unknown_fields)] diff --git a/crates/fractal-client-codegen/templates/lib.rs.in b/crates/fractal-client-codegen/templates/lib.rs.in index cb69c4c2fae..fa9d34c9c63 100644 --- a/crates/fractal-client-codegen/templates/lib.rs.in +++ b/crates/fractal-client-codegen/templates/lib.rs.in @@ -1194,6 +1194,8 @@ fn render_message(code: Option<&ErrorCode>, message: &str, human: bool) -> Strin | ErrorCode::LegacyActionReceiptUntrusted | ErrorCode::RuntimeNotLocal | ErrorCode::PrivateNotesCarrierConflict + | ErrorCode::GrantProfileConflict + | ErrorCode::AssistantGrantAuthorityNotReady | ErrorCode::PrivateNotesUnreachable | ErrorCode::PrivateNotesIndeterminate | ErrorCode::ArrangementExists @@ -2064,6 +2066,11 @@ impl Client { pub async fn assistant_grant(&self, id: &str) -> Result, ClientError> { self.get(&format!("/v1/client/assistant/grants/{}", percent_encode_segment(id.strip_prefix("assistant-grant/").unwrap_or(id)))).await } + /// Inspect with optional conflict witnesses; the default method retains the legacy wire shape. + pub async fn assistant_grant_with_witness(&self, id: &str, witness: bool) -> Result, ClientError> { + let query = if witness { "?witness=1" } else { "" }; + self.get(&format!("/v1/client/assistant/grants/{}{query}", percent_encode_segment(id.strip_prefix("assistant-grant/").unwrap_or(id)))).await + } pub async fn assistant_grant_revoke(&self, id: &str) -> Result, ClientError> { self.post(&format!("/v1/client/assistant/grants/{}/revoke", percent_encode_segment(id.strip_prefix("assistant-grant/").unwrap_or(id))), &serde_json::json!({})).await } diff --git a/crates/fractal-client/src/generated.rs b/crates/fractal-client/src/generated.rs index 14688c04acf..1691601da97 100644 --- a/crates/fractal-client/src/generated.rs +++ b/crates/fractal-client/src/generated.rs @@ -134,6 +134,8 @@ pub enum ErrorCode { PeerTooOld, ValidationFailed, IdempotencyConflict, + GrantProfileConflict, + AssistantGrantAuthorityNotReady, LegacyActionReceiptUntrusted, IssuerRequired, PairingOriginRequired, @@ -5157,6 +5159,40 @@ pub struct AssistantGrant { pub revoked: bool, #[serde(default, skip_serializing_if = "Option::is_none")] pub read_trust: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub conflict: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cleared_conflicts: Option>, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum ExternalGrantProfile { + Assistant, + Service, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum GrantProfileConflictCause { + Revoked, + Expired, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct GrantProfileWitness { + pub grant_id: Option, + pub origin: String, + pub profile: ExternalGrantProfile, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct GrantProfileConflictWitness { + pub grants: Vec, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct ClearedGrantProfileConflictWitness { + pub grants: Vec, + pub cause: GrantProfileConflictCause, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[serde(deny_unknown_fields)] diff --git a/crates/fractal-client/src/lib.rs b/crates/fractal-client/src/lib.rs index e31b340b609..6c381addde3 100644 --- a/crates/fractal-client/src/lib.rs +++ b/crates/fractal-client/src/lib.rs @@ -1280,6 +1280,8 @@ fn render_message(code: Option<&ErrorCode>, message: &str, human: bool) -> Strin | ErrorCode::LegacyActionReceiptUntrusted | ErrorCode::RuntimeNotLocal | ErrorCode::PrivateNotesCarrierConflict + | ErrorCode::GrantProfileConflict + | ErrorCode::AssistantGrantAuthorityNotReady | ErrorCode::PrivateNotesUnreachable | ErrorCode::PrivateNotesIndeterminate | ErrorCode::ArrangementExists @@ -3707,6 +3709,19 @@ impl Client { )) .await } + /// Inspect with optional conflict witnesses; the default method retains the legacy wire shape. + pub async fn assistant_grant_with_witness( + &self, + id: &str, + witness: bool, + ) -> Result, ClientError> { + let query = if witness { "?witness=1" } else { "" }; + self.get(&format!( + "/v1/client/assistant/grants/{}{query}", + percent_encode_segment(id.strip_prefix("assistant-grant/").unwrap_or(id)) + )) + .await + } pub async fn assistant_grant_revoke( &self, id: &str, diff --git a/crates/fractal-daemon/src/tiles/seccomp.rs b/crates/fractal-daemon/src/tiles/seccomp.rs index 68083e6852b..4d7b6ebeba8 100644 --- a/crates/fractal-daemon/src/tiles/seccomp.rs +++ b/crates/fractal-daemon/src/tiles/seccomp.rs @@ -92,6 +92,7 @@ fn jump(code: u32, k: u32, jt: u8, jf: u8) -> libc::sock_filter { const LOAD: u32 = libc::BPF_LD | libc::BPF_W | libc::BPF_ABS; const EQUAL: u32 = libc::BPF_JMP | libc::BPF_JEQ | libc::BPF_K; +#[cfg(any(target_arch = "x86_64", test))] const AT_LEAST: u32 = libc::BPF_JMP | libc::BPF_JGE | libc::BPF_K; const ANY_BIT: u32 = libc::BPF_JMP | libc::BPF_JSET | libc::BPF_K; const RETURN: u32 = libc::BPF_RET | libc::BPF_K; diff --git a/crates/fractal-delivery/src/store/delivery.rs b/crates/fractal-delivery/src/store/delivery.rs index 672e27e928b..7a9c20fe1dd 100644 --- a/crates/fractal-delivery/src/store/delivery.rs +++ b/crates/fractal-delivery/src/store/delivery.rs @@ -935,8 +935,11 @@ impl DeliveryStore for Store { if let Some((deadline, attempts)) = local { return Ok(Some((deadline as u128, attempts))); } + // Pin the request seek, like the other plan-sensitive history reads: + // without ANALYZE, adding a kind-leading index can make SQLite prefer + // a generic subject/kind scan that decodes every deferred request. let count: u32 = connection.query_row( - "SELECT COUNT(*) FROM claims + "SELECT COUNT(*) FROM claims INDEXED BY claims_subscription_deferred_request_index WHERE subject=?1 AND kind='subscription.mission-deferred' AND json_extract(body, '$.fields.request')=?2", params![subject, request], diff --git a/crates/fractal-delivery/src/store/message_send_tests.rs b/crates/fractal-delivery/src/store/message_send_tests.rs index 3ea559bf7e1..de714062a84 100644 --- a/crates/fractal-delivery/src/store/message_send_tests.rs +++ b/crates/fractal-delivery/src/store/message_send_tests.rs @@ -445,8 +445,8 @@ fn assistant_provenance_stamps_authenticated_grant_and_preserves_replica_admissi store.apply(&crate::graph::parse_test_intent( "version 2\nagent \"example-recipient.local\" { workspace \"/tmp/st-test\"; command \"true\"; restart always; }", "node").unwrap(), &BTreeMap::from([("agent/example-recipient.local".to_string(), Vec::new())]), "assistant-recipient").unwrap(); - let grant_subject = "custom/client/assistant-v1-native-fixture"; - let grant_id = "assistant-grant/native-fixture"; + let grant_subject = "custom/client/assistant-v1-0123456789abcdef01234567"; + let grant_id = "assistant-grant/0123456789abcdef01234567"; let session_actor = format!("{principal}/session/{grant_id}"); store.append_claim(&ClaimInput { subject: grant_subject.into(), kind: "custom.client.assistant.v1.granted".into(), @@ -454,12 +454,15 @@ fn assistant_provenance_stamps_authenticated_grant_and_preserves_replica_admissi fields: serde_json::from_value(json!({ "principal":principal, "session_actor":session_actor, "issuer":"person/robin", "disclosure_consent":true, "policy_revision":1, + "credential_hash":"a".repeat(64), "minimal_read_mode":"approval-once", "expires_at_unix_ms":now_ms() as u64 + 60_000, "scopes":["write.assistant.messages"], "recipient_allowlist":["agent/example-recipient.local"], "grant_id":grant_id })).unwrap(), evidence: vec![], expected_subject: None, idempotency_key: None, }).unwrap(); + // Complete fixture authority maintenance before exercising the writer recheck. + while !store.advance_assistant_grant_authority_backfill().unwrap() {} let authorization = assistant_write::AssistantWriteAuthorization { grant_subject: grant_subject.into(), actor: session_actor.clone(), owner: "person/robin".into(), policy_revision: 1, scope: "write.assistant.messages".into(), @@ -491,3 +494,52 @@ fn assistant_provenance_stamps_authenticated_grant_and_preserves_replica_admissi assert_eq!(store.append_assistant_claim_outcome(&wrong_actor, &authorization).unwrap_err().code, "forbidden"); } } + +#[test] +fn writer_recheck_fences_dirty_subject_without_exposing_projection_state() { + let store = Store::open_memory("node").unwrap(); + store.apply(&crate::graph::parse_test_intent( + "version 2\nagent \"example-recipient.local\" { workspace \"/tmp/st-test\"; command \"true\"; restart always; }", "node").unwrap(), + &BTreeMap::from([("agent/example-recipient.local".to_string(), Vec::new())]), "assistant-recipient").unwrap(); + let grant_subject = "custom/client/assistant-v1-0123456789abcdef01234567"; + let grant_id = "assistant-grant/0123456789abcdef01234567"; + let session_actor = format!("assistant/chatgpt/session/{grant_id}"); + let granted = store.append_claim(&ClaimInput { + subject: grant_subject.into(), kind: "custom.client.assistant.v1.granted".into(), + actor: Some("person/robin".into()), + fields: serde_json::from_value(json!({ + "principal":"assistant/chatgpt", "session_actor":session_actor, + "issuer":"person/robin", "disclosure_consent":true, "policy_revision":1, + "credential_hash":"a".repeat(64), "minimal_read_mode":"approval-once", + "expires_at_unix_ms":u64::MAX, "scopes":["write.assistant.messages"], + "grant_id":grant_id + })).unwrap(), + evidence: vec![], expected_subject: None, idempotency_key: None, + }).unwrap(); + // Settle the valid fixture before injecting dirty state; the writer must not repair it. + while !store.advance_assistant_grant_authority_backfill().unwrap() {} + let authorization = assistant_write::AssistantWriteAuthorization { + grant_subject: grant_subject.into(), actor: session_actor, + owner: "person/robin".into(), policy_revision: 1, + scope: "write.assistant.messages".into(), + recipient: Some("agent/example-recipient.local".into()), + }; + let mut input = request(); + input.actor = Some("assistant/chatgpt".into()); + input.fields.insert("from".into(), json!("assistant/chatgpt")); + input.fields.insert("to".into(), json!("agent/example-recipient.local")); + // An unrelated pending claim must not prevent the actual mutation transaction. + store.connection.lock().unwrap().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES('unrelated-claim')", [], + ).unwrap(); + assert!(store.append_assistant_claim_outcome(&input, &authorization).unwrap().1); + input.subject = "message/assistant-dirty-subject-denied".into(); + input.idempotency_key = Some("assistant-dirty-subject-denied".into()); + store.connection.lock().unwrap().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&granted.id], + ).unwrap(); + let error = store.append_assistant_claim_outcome(&input, &authorization).unwrap_err(); + assert_eq!(error.code, "forbidden"); + assert_eq!(error.message, "assistant write authorization changed or expired before commit"); + assert!(store.latest_claim(&input.subject, None).unwrap().is_none()); +} diff --git a/crates/fractal-delivery/src/store/tests.rs b/crates/fractal-delivery/src/store/tests.rs index 3c2ae535a28..3694eeef623 100644 --- a/crates/fractal-delivery/src/store/tests.rs +++ b/crates/fractal-delivery/src/store/tests.rs @@ -92,7 +92,7 @@ fn subscription_retry_queries_use_history_indexes() { let connection = store.readers.get(); let request_plan: String = connection .query_row( - "EXPLAIN QUERY PLAN SELECT COUNT(*) FROM claims + "EXPLAIN QUERY PLAN SELECT COUNT(*) FROM claims INDEXED BY claims_subscription_deferred_request_index WHERE subject=?1 AND kind='subscription.mission-deferred' AND json_extract(body, '$.fields.request')=?2", params![subject, "request-a"], diff --git a/crates/fractal-store/src/store/assistant_write.rs b/crates/fractal-store/src/store/assistant_write.rs index 7c5691e3a06..c0ab6fc4894 100644 --- a/crates/fractal-store/src/store/assistant_write.rs +++ b/crates/fractal-store/src/store/assistant_write.rs @@ -1,5 +1,6 @@ -//! Server-established assistant provenance, checked in the mutation's writer transaction. +//! Server-established assistant provenance, rechecked against projected authority in the mutation's writer transaction. use super::*; +use smallclaims::store::assistant_grant_authority as authority; #[derive(Clone, Debug)] pub struct AssistantWriteAuthorization { @@ -17,12 +18,6 @@ impl AssistantWriteAuthorization { } } -pub fn principal(fields: &Value) -> Option<&str> { - match fields.get("principal") { - None => Some("assistant/chatgpt"), - Some(value) => value.as_str().filter(|principal| matches!(*principal, "assistant/chatgpt" | "assistant/mcp")), - } -} pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let granted = authorized_grant(connection, origin, authorization)?; @@ -32,27 +27,28 @@ pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &As pub fn authorized_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let denied = || FractalError::new("forbidden", "assistant write authorization changed or expired before commit"); - let claim = |kind: &str| -> Result, FractalError> { - connection.query_row(/* sqlite-large-value: allow-for-now lv-hd82c937baff5 owner=fractal_store::store::assistant_write TODO=trace-statement-and-value-representation */ &latest_claim_of_kind_query(), - params![authorization.grant_subject,kind],claim_from_row).optional().map_err(internal) + let authority_error = |error: FractalError| { + if matches!(error.code, "assistant-grant-authority-not-ready" | "assistant-grant-subject-not-ready") { + denied() + } else { error } }; - let granted = claim("custom.client.assistant.v1.granted")?.ok_or_else(denied)?; - let policy_claim = claim("custom.client.assistant.v1.policy")?; + let granted = authority::latest(connection, &authorization.grant_subject, authority::GRANTED).map_err(authority_error)? + .ok_or_else(denied)?; + let policy_claim = authority::transition(connection, &granted, authority::POLICY).map_err(authority_error)?; let policy = policy_claim.as_ref().unwrap_or(&granted); - if granted.origin != origin || policy.origin != origin || claim("custom.client.assistant.v1.revoked")?.is_some() { + if granted.origin != origin || policy.origin != origin + || !authority::structurally_valid(&granted, policy) + || authority::transition(connection, &granted, authority::REVOKED).map_err(authority_error)?.is_some() { return Err(denied()); } let fields = &policy.body["fields"]; - let principal = principal(fields).ok_or_else(denied)?; - if self::principal(&granted.body["fields"]) != Some(principal) - || ["grant_id", "session_actor", "issuer"].iter().any(|key| fields[*key] != granted.body["fields"][*key]) + let principal = authority::principal(fields).ok_or_else(denied)?; + if fields.get("profile").is_some_and(|profile| profile != "assistant") || authorization.principal() != principal || fields["session_actor"] != authorization.actor - || fields["session_actor"].as_str().and_then(|actor| actor.strip_prefix(principal)) - .and_then(|suffix| suffix.strip_prefix("/session/")) != fields["grant_id"].as_str() || granted.actor.as_deref() != Some(authorization.owner.as_str()) || policy.actor.as_deref() != Some(authorization.owner.as_str()) - || fields["issuer"] != authorization.owner || fields["disclosure_consent"] != true + || fields["issuer"] != authorization.owner || fields["policy_revision"].as_u64() != Some(authorization.policy_revision) || fields["expires_at_unix_ms"].as_u64().map(u128::from).is_none_or(|expiry| expiry <= now_ms()) || !fields["scopes"].as_array().is_some_and(|scopes| scopes.iter().any(|scope| scope.as_str() == Some(&authorization.scope))) @@ -103,14 +99,113 @@ pub fn validate_replicated(kind: &str, actor: Option<&str>, fields: &Value) -> R mod tests { use super::*; + fn transition_fixture() -> (Store, String, Value) { + let store = Store::open_memory("local").unwrap(); + let suffix = "0123456789abcdef01234567"; + let subject = format!("custom/client/assistant-v1-{suffix}"); + let body = json!({"fields":{ + "grant_id":format!("assistant-grant/{suffix}"), "issuer":"person/owner", + "session_actor":format!("assistant/chatgpt/session/assistant-grant/{suffix}"), + "credential_hash":"a".repeat(64), "minimal_read_mode":"approval-once", + "disclosure_consent":true, "scopes":["write.assistant.messages"], + "expires_at_unix_ms":u64::MAX + }}); + insert_transition(&store, &subject, authority::GRANTED, "person/owner", &body); + (store, subject, body) + } + + fn insert_transition(store: &Store, subject: &str, kind: &str, actor: &str, body: &Value) -> ClaimRecord { + store.append_claim(&ClaimInput { + subject: subject.into(), kind: kind.into(), actor: Some(actor.into()), + fields: serde_json::from_value(body["fields"].clone()).unwrap(), + evidence: Vec::new(), expected_subject: None, idempotency_key: None, + }).unwrap() + } + + #[test] + fn projected_transition_ignores_actor_overlay_flood() { + let (store, subject, body) = transition_fixture(); + let granted = authority::latest(&store.readers.get(), &subject, authority::GRANTED).unwrap().unwrap(); + let valid = insert_transition(&store, &subject, authority::POLICY, "person/owner", &body); + let mut prior = None; + for count in [32, 512, 7900] { + for index in 0..count { + let mut overlay = body.clone(); + overlay["fields"]["nonce"] = json!(format!("{count}-{index}")); + insert_transition(&store, &subject, authority::POLICY, "person/other", &overlay); + } + let selected = authority::transition(&store.readers.get(), &granted, authority::POLICY).unwrap().unwrap(); + assert_eq!(selected.id, valid.id); + let connection = store.readers.get(); + let args = params![subject, authority::POLICY, granted.origin, "person/owner", granted.id]; + let mut statement = connection.prepare(authority::TRANSITION_QUERY).unwrap(); + let _: String = statement.query_row(args, |row| row.get(0)).unwrap(); + let cost = statement.get_status(rusqlite::StatementStatus::VmStep); + if let Some(prior) = prior { assert!(cost <= prior + 20, "{prior} -> {cost}"); } + prior = Some(cost); + let plan = connection.prepare(&format!("EXPLAIN QUERY PLAN {}", authority::TRANSITION_QUERY)).unwrap() + .query_map(args, |row| row.get::<_, String>(3)).unwrap() + .collect::>>().unwrap().join("; "); + assert!(plan.contains("assistant_grant_authority_transition_index"), "{plan}"); + assert!(!plan.contains("USE TEMP B-TREE FOR ORDER BY"), "{plan}"); + } + } + + #[test] + fn projected_transition_ignores_malformed_newer_policies_and_revocations() { + let (store, subject, body) = transition_fixture(); + let granted = authority::latest(&store.readers.get(), &subject, authority::GRANTED).unwrap().unwrap(); + for kind in [authority::POLICY, authority::REVOKED] { + let valid = insert_transition(&store, &subject, kind, "person/owner", &body); + let mut patches = vec![ + json!({"principal":null}), json!({"principal":"assistant/mcp"}), + json!({"profile":null}), json!({"profile":"service"}), + json!({"issuer":"person/other"}), json!({"grant_id":"assistant-grant/other"}), + ]; + if kind.ends_with(".policy") { + patches.extend([ + json!({"session_actor":"assistant/chatgpt/session/other"}), + json!({"minimal_read_mode":"unknown"}), json!({"disclosure_consent":false}), + json!({"expires_at_unix_ms":null}), json!({"expires_at_unix_ms":-1}), + json!({"expires_at_unix_ms":1.5}), json!({"scopes":["unknown"]}), + json!({"expires_at_unix_ms":1e19}), + json!({"scopes":[null]}), json!({"credential":"secret"}), + json!({"credential_hash":"invalid"}), json!({"code_hash":null}), + ]); + } + for patch in patches { + let mut malformed = body.clone(); + malformed["fields"].as_object_mut().unwrap().extend(patch.as_object().unwrap().clone()); + insert_transition(&store, &subject, kind, "person/owner", &malformed); + } + let selected = authority::transition(&store.readers.get(), &granted, kind).unwrap().unwrap(); + assert_eq!(selected.id, valid.id); + } + } + + #[test] + fn projected_transition_accepts_raw_hex_grant_identity() { + let store = Store::open_memory("local").unwrap(); + let suffix = "0123456789abcdef01234567"; + let subject = format!("custom/client/assistant-v1-{suffix}"); + let body = json!({"fields":{"grant_id":suffix,"issuer":"person/owner", + "session_actor":format!("assistant/chatgpt/session/{suffix}"), + "credential_hash":"a".repeat(64),"minimal_read_mode":"approval-once", + "disclosure_consent":true,"scopes":[],"expires_at_unix_ms":u64::MAX}}); + let granted = insert_transition(&store, &subject, authority::GRANTED, "person/owner", &body); + let valid = insert_transition(&store, &subject, authority::POLICY, "person/owner", &body); + let selected = authority::transition(&store.readers.get(), &granted, authority::POLICY).unwrap().unwrap(); + assert_eq!(selected.id, valid.id); + } + #[test] fn grant_principal_defaults_only_absent_legacy_fields_to_chatgpt() { - assert_eq!(principal(&json!({})), Some("assistant/chatgpt")); + assert_eq!(authority::principal(&json!({})), Some("assistant/chatgpt")); for expected in ["assistant/chatgpt", "assistant/mcp"] { - assert_eq!(principal(&json!({"principal":expected})), Some(expected)); + assert_eq!(authority::principal(&json!({"principal":expected})), Some(expected)); } for forged in [Value::Null, json!("assistant/other"), json!("person/other"), json!(7)] { - assert_eq!(principal(&json!({"principal":forged})), None); + assert_eq!(authority::principal(&json!({"principal":forged})), None); } } @@ -139,4 +234,5 @@ mod tests { assert!(refuse_unverified("message.sent", Some(principal), Some(principal), false).is_err()); } } + } diff --git a/crates/fractal-store/src/store/messages_shard.rs b/crates/fractal-store/src/store/messages_shard.rs index 32b016d9b35..ecbe4139dff 100644 --- a/crates/fractal-store/src/store/messages_shard.rs +++ b/crates/fractal-store/src/store/messages_shard.rs @@ -463,6 +463,7 @@ impl FleetAuthority for GraphAuthority { FleetAuthority::fleet_generation(&self.graph()?.graph) } + fn fleet_membership(&self) -> anyhow::Result { FleetAuthority::fleet_membership(&self.graph()?.graph) } diff --git a/crates/fractal-store/src/store/runtime.rs b/crates/fractal-store/src/store/runtime.rs index 03e7204d77d..dc3b9a2fbd9 100644 --- a/crates/fractal-store/src/store/runtime.rs +++ b/crates/fractal-store/src/store/runtime.rs @@ -845,6 +845,178 @@ impl FractalRuntime { mod schema_install_tests { use super::*; + #[test] + fn assistant_projection_backfills_existing_claims_without_changing_baseline_schema() { + use smallclaims::store::assistant_grant_authority as authority; + use std::time::Duration; + + const OBSOLETE_INDEXES: [&str; 3] = [ + "claims_assistant_v1_principal_index", + "claims_assistant_v1_principal_expiry_index", + "claims_assistant_v1_transition_index", + ]; + + fn snapshot(connection: &Connection) -> Vec> { + connection + .prepare("SELECT * FROM claims ORDER BY store_index") + .unwrap() + .query_map([], |row| { + (0..row.as_ref().column_count()).map(|column| row.get(column)).collect() + }) + .unwrap() + .collect::>() + .unwrap() + } + + fn claims_indexes(connection: &Connection) -> Vec<(String, Option)> { + connection + .prepare("SELECT name,sql FROM sqlite_schema WHERE type='index' AND tbl_name='claims' ORDER BY name") + .unwrap() + .query_map([], |row| Ok((row.get(0)?, row.get(1)?))) + .unwrap() + .collect::>() + .unwrap() + } + + fn append(connection: &Connection, id: &str, slot: u8, kind: &str, principal: &str, expiry: u64) { + let suffix = format!("{slot:024x}"); + let grant_id = format!("assistant-grant/{suffix}"); + let body = json!({"fields": { + "grant_id": grant_id, + "issuer": "person/owner", + "principal": principal, + "profile": "assistant", + "session_actor": format!("{principal}/session/{grant_id}"), + "credential_hash": "a".repeat(64), + "minimal_read_mode": "approval-once", + "disclosure_consent": true, + "expires_at_unix_ms": expiry, + "scopes": ["read.assistant.summary"] + }}); + connection.execute( + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES(?1,'batch',?2,?3,'node','person/owner',?4,'[]','1')", + params![id, format!("custom/client/assistant-v1-{suffix}"), kind, body.to_string()], + ).unwrap(); + } + + // Supported older stores retain their version and raw evidence. An intermediate + // build's indexes must also survive: rollback is additive, never DROP INDEX. + for version in [18, 19, fractal_schema::STORAGE_VERSION] { + for had_obsolete_indexes in [false, true] { + let directory = tempfile::tempdir().unwrap(); + let path = directory.path().join("claims.sqlite"); + // Use the public constructor so fleet-generation state and all other + // smallclaims initialization exist before exercising historical raw writes. + drop(Store::open(&path, "node").unwrap()); + let connection = Connection::open(&path).unwrap(); + let baseline_indexes = claims_indexes(&connection); + assert!(baseline_indexes.iter().any(|(name, _)| name == "claims_assistant_v1_credential_index")); + assert!(baseline_indexes.iter().all(|(name, _)| !OBSOLETE_INDEXES.contains(&name.as_str()))); + if had_obsolete_indexes { + // Historical DDL is a rollback fixture, not a production installation. + connection.execute_batch( + "CREATE INDEX claims_assistant_v1_principal_index + ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); + CREATE INDEX claims_assistant_v1_principal_expiry_index + ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), + json_extract(body,'$.fields.expires_at_unix_ms')); + CREATE INDEX claims_assistant_v1_transition_index + ON claims(subject, kind, origin, actor, store_index);" + ).unwrap(); + } + connection.pragma_update(None, "user_version", version).unwrap(); + connection.execute( + "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) + VALUES('batch','node',1,'hash','1')", [], + ).unwrap(); + append(&connection, "active", 1, authority::GRANTED, "assistant/chatgpt", 50); + append(&connection, "extended", 1, authority::POLICY, "assistant/chatgpt", 200); + append(&connection, "expired", 2, authority::GRANTED, "assistant/chatgpt", 50); + append(&connection, "revoked", 3, authority::GRANTED, "assistant/chatgpt", 200); + append(&connection, "revoke", 3, authority::REVOKED, "assistant/chatgpt", 200); + append(&connection, "mcp", 4, authority::GRANTED, "assistant/mcp", 200); + append(&connection, "unrelated", 5, "custom.test.recorded", "assistant/chatgpt", 200); + // These fixture rows model durable local appends. Truly old, + // unmarked raw evidence is ambiguous and must remain pending. + for id in ["active", "extended", "expired", "revoked", "revoke", "mcp"] { + connection.execute( + "INSERT INTO assistant_grant_local_appends(claim_id) VALUES(?1)", [id], + ).unwrap(); + } + let before = snapshot(&connection); + let indexes_before = claims_indexes(&connection); + drop(connection); + + let connection = Connection::open(&path).unwrap(); + migrate_schema(&connection).unwrap(); + install_initial_schema(&connection, false).unwrap(); + authority::install(&connection, "node").unwrap(); + assert!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).is_err()); + // A zero-budget slice makes partial progress without marking it ready. + assert!(!authority::backfill_slice(&connection, Duration::ZERO).unwrap()); + assert!(authority::ready(&connection).is_err()); + while !authority::backfill_slice(&connection, Duration::from_secs(1)).unwrap() {} + authority::ready(&connection).unwrap(); + assert_eq!(snapshot(&connection), before, "version {version}: raw evidence"); + assert_eq!(claims_indexes(&connection), indexes_before, "projection must not build or drop raw claims indexes"); + assert_eq!( + connection.pragma_query_value(None, "user_version", |row| row.get::<_, u32>(0)).unwrap(), + version, + ); + let active = authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).unwrap(); + assert_eq!(active.iter().map(|claim| claim.id.as_str()).collect::>(), vec!["active"]); + assert_eq!( + authority::candidates(&connection, "assistant/mcp", "person/owner", Some(100), None, None).unwrap() + .iter().map(|claim| claim.id.as_str()).collect::>(), + vec!["mcp"], + ); + assert_eq!( + authority::candidates(&connection, "assistant/chatgpt", "person/owner", None, None, None).unwrap().len(), + 3, + "no cutoff retains expired and revoked validation candidates", + ); + let plan = connection.prepare(&format!("EXPLAIN QUERY PLAN {}", authority::CANDIDATES_QUERY)).unwrap() + .query_map(params!["assistant/chatgpt", "person/owner", authority::expiry_key(100), Option::::None, Option::::None], |row| row.get::<_, String>(3)) + .unwrap().collect::>>().unwrap(); + assert!(plan.iter().any(|step| step.contains("SEARCH") + && step.contains("assistant_grant_effective_active_index") + && step.contains("principal=? AND owner=? AND revoked=? AND expires_at>?")), "{plan:?}"); + assert!(plan.iter().all(|step| !step.contains("SCAN claims") && !step.contains("SEARCH claims")), "{plan:?}"); + + // An older build's raw revoke fences its subject before and + // after reconciliation: origin text cannot authenticate it, + // but pending revocation must not authorize a stale grant. + append(&connection, "late-revoke", 1, authority::REVOKED, "assistant/chatgpt", 200); + authority::ready(&connection).unwrap(); + assert_eq!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None) + .unwrap().iter().map(|claim| claim.id.as_str()).collect::>(), vec!["active"]); + assert!(!authority::contains(&connection, "active").unwrap()); + while !authority::backfill_slice(&connection, Duration::from_secs(1)).unwrap() {} + assert_eq!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None) + .unwrap().iter().map(|claim| claim.id.as_str()).collect::>(), vec!["active"]); + assert!(!authority::contains(&connection, "active").unwrap()); + assert!(!authority::contains(&connection, "late-revoke").unwrap()); + let after = snapshot(&connection); + let cookie: u32 = connection.pragma_query_value(None, "schema_version", |row| row.get(0)).unwrap(); + drop(connection); + + let connection = Connection::open(&path).unwrap(); + migrate_schema(&connection).unwrap(); + install_initial_schema(&connection, false).unwrap(); + authority::install(&connection, "node").unwrap(); + authority::ready(&connection).unwrap(); + assert_eq!(snapshot(&connection), after); + assert_eq!(claims_indexes(&connection), indexes_before); + assert_eq!( + connection.pragma_query_value(None, "schema_version", |row| row.get::<_, u32>(0)).unwrap(), + cookie, + "an unchanged reopen must not rebuild projection or baseline indexes", + ); + } + } + } + #[test] fn complete_runtime_schema_does_not_take_a_held_writer_lock() { let directory = tempfile::tempdir().unwrap(); diff --git a/crates/fractal-store/src/store/shared.rs b/crates/fractal-store/src/store/shared.rs index d796a6ecc65..5cd56982aec 100644 --- a/crates/fractal-store/src/store/shared.rs +++ b/crates/fractal-store/src/store/shared.rs @@ -259,6 +259,15 @@ impl Store { .map_err(internal)?; if inserted != 0 { let index = transaction.last_insert_rowid() as u64; + if matches!(claim.kind.as_str(), + smallclaims::store::assistant_grant_authority::GRANTED + | smallclaims::store::assistant_grant_authority::POLICY + | smallclaims::store::assistant_grant_authority::REVOKED) + { + smallclaims::store::assistant_grant_authority::refresh_claim( + &transaction, &claim.id, + ).map_err(internal)?; + } let effective = register_operation_tx(&transaction, claim).map_err(internal)?; if effective { insert_event( diff --git a/crates/fractal/src/assistant_grant_authority_wake_tests.rs b/crates/fractal/src/assistant_grant_authority_wake_tests.rs new file mode 100644 index 00000000000..f42a9b6c7b1 --- /dev/null +++ b/crates/fractal/src/assistant_grant_authority_wake_tests.rs @@ -0,0 +1,85 @@ +use super::*; +use smallclaims::store::assistant_grant_authority as authority; + +#[tokio::test] +async fn completed_authority_reconciles_older_build_appends_without_reopen() { + let store = Arc::new(Store::open_memory("node").unwrap()); + while !store.advance_assistant_grant_authority_backfill().unwrap() {} + assert!(authority::ready(&store.readers.get()).is_ok()); + let task = tokio::spawn(build_assistant_grant_authority(store.clone())); + // The old writer bypasses projection hooks. Only the persistent insert + // trigger and the store's commit notification connect it to maintenance. + // An invalid grant is still durable dirty work and must be reconciled. + store.connection.write().execute_batch( + "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) + VALUES('batch/old-writer','node',1,'old-writer','1');" + ).unwrap(); + // Two independently committed appends ensure this exercises an already + // completed worker, even if its first poll races the initial raw append. + for id in ["claim/old-writer/first", "claim/old-writer/second"] { + store.connection.write().execute( + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES(?1,'batch/old-writer','custom/client/assistant-v1-invalid', + 'custom.client.assistant.v1.granted','node','person/owner','{}','[]','1')", + [id], + ).unwrap(); + authority::ready(&store.readers.get()).unwrap(); + tokio::time::timeout(Duration::from_secs(5), async { + loop { + if !authority::maintenance_pending(&store.readers.get()).unwrap() { break; } + tokio::task::yield_now().await; + } + }).await.expect("a completed projection wakes and drains compatibility work"); + assert!(!authority::contains(&store.readers.get(), id).unwrap()); + } + task.abort(); +} + +#[tokio::test] +async fn authority_commit_between_completed_drain_and_wait_is_not_lost() { + let store = Arc::new(Store::open_memory("node").unwrap()); + while !store.advance_assistant_grant_authority_backfill().unwrap() {} + let mut maintenance = AssistantGrantAuthorityMaintenance::new(store.clone()); + assert!(maintenance.advance().await.unwrap(), "the drain completed"); + // Deterministically place this commit after the completed drain and before + // waiting. No scheduler timing or sleep is needed to hit the race boundary. + store.connection.write().execute_batch( + "BEGIN; + INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) + VALUES('batch/race','node',1,'race','1'); + INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES('claim/race','batch/race','custom/client/assistant-v1-invalid', + 'custom.client.assistant.v1.granted','node','person/owner','{}','[]','1'); + COMMIT;" + ).unwrap(); + authority::ready(&store.readers.get()).unwrap(); + assert!(authority::maintenance_pending(&store.readers.get()).unwrap()); + tokio::time::timeout(Duration::from_secs(5), maintenance.changes.changed()) + .await.expect("the intervening commit stays visible") + .expect("the observer remains registered"); + assert!(maintenance.advance().await.unwrap()); + assert!(authority::ready(&store.readers.get()).is_ok()); + assert!(!authority::maintenance_pending(&store.readers.get()).unwrap()); +} + +#[tokio::test] +async fn authority_maintenance_shutdown_exits_and_unregisters_its_observer() { + let store = Arc::new(Store::open_memory("node").unwrap()); + while !store.advance_assistant_grant_authority_backfill().unwrap() {} + let mut maintenance = AssistantGrantAuthorityMaintenance::new(store.clone()); + assert!(maintenance.advance().await.unwrap()); + let mut changes = maintenance.changes.clone(); + let task = tokio::spawn(maintenance.run()); + tokio::task::yield_now().await; + task.abort(); + assert!(task.await.unwrap_err().is_cancelled(), "shutdown exits the loop"); + // Only the registered observer owns the sender. A closed receiver proves + // cancellation dropped the observer callback, not just the task's receiver. + tokio::time::timeout(Duration::from_secs(5), changes.changed()).await + .expect("shutdown drops the observer without waiting for another commit") + .expect_err("no observer sender remains registered"); + store.connection.write().execute( + "INSERT INTO meta(key,value) VALUES('authority-after-shutdown','1')", [], + ).unwrap(); + assert!(changes.has_changed().is_err(), "later commits cannot invoke the removed observer"); +} diff --git a/crates/fractal/src/main.rs b/crates/fractal/src/main.rs index 66ffe4bc5ba..fc332287378 100644 --- a/crates/fractal/src/main.rs +++ b/crates/fractal/src/main.rs @@ -7767,6 +7767,7 @@ async fn run_up(args: UpArgs) -> Result<()> { spawn_publication_evidence(store.clone()); tokio::spawn(build_transport_observation_index(store.clone())); tokio::spawn(build_operation_claim_digests(store.clone())); + tokio::spawn(build_assistant_grant_authority(store.clone())); startup_telemetry.serving(); let ready_at = Instant::now(); startup_phases.log_ready( @@ -20816,6 +20817,71 @@ async fn build_transport_observation_index(store: Arc) { } } +/// Continue the persisted authority cursor after serving begins, then reconcile +/// compatibility-trigger work on commits. Subscribe before checking readiness so +/// an older-build append between the check and the wait cannot be lost. +async fn build_assistant_grant_authority(store: Arc) { + AssistantGrantAuthorityMaintenance::new(store).run().await; +} + +/// Own the subscription for exactly the maintenance task's lifetime. Splitting +/// one page from the wait also makes the drain-to-wait boundary explicit. +struct AssistantGrantAuthorityMaintenance { + store: Arc, + changes: tokio::sync::watch::Receiver<()>, + _observer: smallclaims::sqlite::CommitObserver, +} + +impl AssistantGrantAuthorityMaintenance { + fn new(store: Arc) -> Self { + let (changed, changes) = tokio::sync::watch::channel(()); + let observer = store.observe_commits(move |connection| { + if connection.is_autocommit() { + changed.send_replace(()); + } + }); + Self { store, changes, _observer: observer } + } + + async fn advance(&mut self) -> Result { + // Consume before the read, not after draining: a commit between the + // read/drain and changed().await must remain an unseen generation. + self.changes.borrow_and_update(); + let worker = self.store.clone(); + tokio::task::spawn_blocking(move || { + if !worker.assistant_grant_authority_maintenance_pending()? { + return Ok(true); + } + worker.advance_assistant_grant_authority_backfill() + }).await? + } + + async fn run(mut self) { + loop { + match self.advance().await { + Ok(true) => { + if self.changes.changed().await.is_err() { + return; + } + continue; + } + Ok(false) => {} + Err(error) if maintenance_contention(&error) => {} + error => { + stderr_message("st", format_args!("assistant grant authority backfill stopped: {error:?}; restart resumes its committed cursor")); + return; + } + } + // Each page releases the writer. Yield scheduling, never time-based + // pacing: persisted work resumes immediately in another transaction. + tokio::task::yield_now().await; + } + } +} + +#[cfg(test)] +mod assistant_grant_authority_wake_tests; + /// This starts only after both APIs serve. Each page reads up to 32 operation claims on a /// reader, then joins the managed background writer queue only to insert their keys, and /// yields for 100 ms. The operation audit reads bodies until the last page marks it ready. diff --git a/crates/fractal/tests/assistant_native.rs b/crates/fractal/tests/assistant_native.rs index f12a6747757..9cbce98d7ec 100644 --- a/crates/fractal/tests/assistant_native.rs +++ b/crates/fractal/tests/assistant_native.rs @@ -604,7 +604,7 @@ async fn writer_transaction_rechecks_policy_revision_actor_scope_and_revocation( } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn synchronous_send_rechecks_revocation_and_scope_removal_before_commit() { +async fn synchronous_send_rechecks_pending_subject_revocation_and_scope_removal_before_commit() { let h = Arc::new(Harness::new()); let paired = h.pair().await; let gate = h.root.path().join("mutation-gate"); @@ -613,10 +613,10 @@ async fn synchronous_send_rechecks_revocation_and_scope_removal_before_commit() let count_messages = || connection.query_row( "SELECT count(*) FROM claims WHERE kind='message.sent'", [], |row| row.get::<_, u64>(0), ).unwrap(); - for revoke in [false, true] { + for change in ["pending-subject", "scope", "revocation"] { h.policy(&paired, scopes()).await; let before = count_messages(); - let request = h.message(AGENT, if revoke { "held-revoke" } else { "held-scope" }).await; + let request = h.message(AGENT, &format!("held-{change}")).await; for name in ["hold", "entered", "release", "done"] { let path = gate.join(name); if path.exists() { std::fs::remove_file(path).unwrap(); } @@ -633,7 +633,14 @@ async fn synchronous_send_rechecks_revocation_and_scope_removal_before_commit() tokio::time::sleep(std::time::Duration::from_millis(5)).await; } assert!(!send.is_finished(), "synchronous send must still await its mutation"); - if revoke { + if change == "pending-subject" { + let granted = h.state.store.latest_claim( + &grant_subject(&paired), Some("custom.client.assistant.v1.granted"), + ).unwrap().unwrap(); + connection.execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&granted.id], + ).unwrap(); + } else if change == "revocation" { h.owner("POST", &grant_path(&paired, "/revoke"), &json!({})).await; } else { h.owner("POST", &grant_path(&paired, "/policy"), &AssistantGrantPolicy { @@ -650,7 +657,16 @@ async fn synchronous_send_rechecks_revocation_and_scope_removal_before_commit() let (status, denial) = send.await.unwrap(); assert!(!status.is_success(), "{denial}"); assert_eq!(denial["code"], "forbidden", "{denial}"); + assert_eq!(denial["message"], "assistant write authorization changed or expired before commit"); + assert!(!denial.to_string().contains("not-ready"), "{denial}"); assert_eq!(count_messages(), before, "denied send must append no message claim"); + if change == "pending-subject" { + connection.execute( + "DELETE FROM assistant_grant_dirty WHERE claim_id IN + (SELECT id FROM claims WHERE subject=?1)", + [grant_subject(&paired)], + ).unwrap(); + } } } diff --git a/crates/fractal/tests/daemon_cost.rs b/crates/fractal/tests/daemon_cost.rs index 646de49fc39..38ca9d29f11 100644 --- a/crates/fractal/tests/daemon_cost.rs +++ b/crates/fractal/tests/daemon_cost.rs @@ -48,6 +48,8 @@ //! - `ST_BENCH_DIR` keeps generated stores for the next run, as for `daemon_bench`. //! - `ST_COST_REPORT` writes the measurements as JSON to that path. +mod assistant_admission; + use fractal_daemon::ConversationReadsStore; use fractal_daemon::CustomStore; use fractal_daemon::AdhocWorkStore; diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs new file mode 100644 index 00000000000..44fc088633b --- /dev/null +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -0,0 +1,752 @@ +//! Opt-in, real HTTP/Unix daemon measurement (not a router oneshot or mocked daemon). +//! Run this same source sequentially on each revision, from that worktree root. +//! Bind the build to its source revision and select the executable from Cargo JSON, +//! NEVER by searching a shared target directory for `integration-*` (stale head/base +//! binaries can coexist). `baseline` is a scenario label, NOT executable identity. +//! ```sh +//! export ST_ADMISSION_SOURCE_ROOT="$PWD" +//! export ST_ADMISSION_EXPECT_REVISION="$(git rev-parse HEAD)" +//! export ST_ADMISSION_BUILD_REVISION="$ST_ADMISSION_EXPECT_REVISION" +//! export ST_ADMISSION_BUILD_PROVENANCE="git worktree; harness backport only; cargo command below" +//! export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$PWD/tmp/867-admission/target}" +//! mkdir -p "$PWD/tmp/867-admission" +//! cargo test --release -p fractal --test integration --no-run --message-format=json > "$PWD/tmp/867-admission/build.jsonl" +//! export ST_ADMISSION_BINARY="$(jq -rs '[.[] | select(.reason == "compiler-artifact" and .target.name == "integration" and .profile.test and .executable != null) | .executable] | unique | if length == 1 then .[0] else error("expected one integration test executable") end' "$PWD/tmp/867-admission/build.jsonl")" +//! # Like-for-like counts: run N=2 AND N=5 at BOTH revisions; fresh profiles. +//! # Set variant=baseline on base, indexed on head. Do not reuse an old binary. +//! for n in 2 5; do +//! ST3_PROFILE_DIR="$PWD/tmp/867-admission/$ST_ADMISSION_EXPECT_REVISION-n$n-profile" ST3_PROFILE_SLOW_MS=0 ST_ADMISSION_VARIANT=indexed ST_ADMISSION_LOCAL_ACTIVE="$n" ST_ADMISSION_READ_COUNTS_ONLY=1 ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=0 ST_ADMISSION_FOREIGN_ACTIVE=0 ST_ADMISSION_REPORT="$PWD/tmp/867-admission/$ST_ADMISSION_EXPECT_REVISION-n$n.json" "$ST_ADMISSION_BINARY" daemon_cost::assistant_admission::authenticated_get_during_pairing --exact --nocapture --test-threads=1 +//! done +//! # Head only, full extended q39: 2 local + 3 authenticated foreign grants, +//! # 10000 expired grants/principal, 3 renewals each, 1000 overlays/active grant, +//! # 200 concurrent GET/completion pairs/mode; do NOT set READ_COUNTS_ONLY. +//! ST3_PROFILE_DIR="$PWD/tmp/867-admission/$ST_ADMISSION_EXPECT_REVISION-q39-profile" ST3_PROFILE_SLOW_MS=0 ST_ADMISSION_VARIANT=indexed ST_ADMISSION_LOCAL_ACTIVE=2 ST_ADMISSION_HISTORY=10000 ST_ADMISSION_SAMPLES=200 ST_ADMISSION_FOREIGN_ACTIVE=3 ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=1000 ST_ADMISSION_REPORT="$PWD/tmp/867-admission/$ST_ADMISSION_EXPECT_REVISION-q39.json" "$ST_ADMISSION_BINARY" daemon_cost::assistant_admission::authenticated_get_during_pairing --exact --nocapture --test-threads=1 +//! ``` +//! Backport to base d477c67ad1: copy this file, add `mod assistant_admission;` to +//! crates/fractal/tests/daemon_cost.rs, and replace ONLY `revision_api`'s body +//! with the documented base body below. Build there using the commands above; +//! change VARIANT to baseline in the counts loop. Base supports local N=2/5, +//! but requires READ_COUNTS_ONLY=1, FOREIGN_ACTIVE=0, WRONG_ORIGIN_OVERLAYS=0. +//! It has no provenance API and does not ignore foreign overlays or expose an indexed probe. +//! For a git archive (no .git), set ST_ADMISSION_SOURCE_REVISION to the archived +//! full commit ID and ST_ADMISSION_SOURCE_PROVENANCE to the exact archive command +//! and source/build evidence location; retain the build env above and set EXPECT +//! to that ID explicitly instead of git rev-parse. These are declared provenance, +//! not a claim that a reused binary was built from that archive. The executable's +//! embedded revision MUST match EXPECT; its canonical path and SHA256 are reported. +//! A worktree report records actual `git rev-parse HEAD`; archives record null for +//! that observation and separately record the explicit source revision/evidence. +//! Counts are observations, not expectations: rerun true base N=2 to establish or +//! explain the previously cited 4/12/16 (auth/caller-bound/approval-once) counts. +//! Old base 8/8/9 with identical head SQL is not evidence of base behavior without +//! executable identity. Compare direct auth separately from GET: receipt/proof work +//! and the number of live grants differ. Never relabel an existing report as base. +//! Prior run: `git archive d477c67ad1` into a base directory, harness-only +//! backport, then `cargo test --release -p fractal --test integration ...` in a +//! shared target directory previously used by head. The retained report +//! /var/tmp/867c-evidence/fix/base-counts-1.json lacked executable identity. +//! This fixture serves routers IN PROCESS: daemon_bench's standalone binary +//! discovery cannot explain its direct-auth measurement. A reused integration +//! executable/dependency artifact is a hypothesis, not an established cause. +//! Source inspection of d477c67ad1 authenticate/session implies four acquisitions +//! (digest lookup, claim_by_id, POLICY, REVOKED), independent of N. GET 12/16 must +//! be remeasured with the same route, proof, receipt flush and profiling scope; +//! they are not asserted as expected counts by this fixture. Retain reports and +//! build JSON to distinguish executable reuse from instrumentation/scope differences. +//! ST_ADMISSION_HISTORY (default 10000) is expired grants PER principal; ST_ADMISSION_SAMPLES +//! (default 200) is measured GET/completion pairs PER read mode. Setup and proof creation are +//! outside timing. Each pair starts behind a barrier, with no sleeps, polling, retries or timers. +//! ST_ADMISSION_FOREIGN_ACTIVE optionally adds verified same-profile active foreign grants +//! (default 0; use 3 for the provenance-check scenario). ST_ADMISSION_REPORT optionally +//! saves the complete JSON report. Hardware is observed from uname/lscpu, not inferred. +//! ST_ADMISSION_LOCAL_ACTIVE (default 2, minimum 2) creates that many local active +//! grants, including the two measured modes; total N is local + FOREIGN_ACTIVE. +//! Extra local grants use caller-bound-allow and remain active throughout sampling. +//! Each expired grant has three still-expired POLICY renewals. Each active session has +//! ST_ADMISSION_WRONG_ORIGIN_OVERLAYS (default 1000; 0 allowed) authenticated wrong-origin +//! overlays, alternating POLICY and REVOKED; every measured read must still succeed. +//! ST_ADMISSION_READ_COUNTS_ONLY=1 measures only read counts: it skips the +//! candidate SQL, latency pairs, the q39 gate and the release-build requirement. +//! Read counts require a fresh ST3_PROFILE_DIR and ST3_PROFILE_SLOW_MS=0. The existing +//! profile `read_acquisitions` counts pooled read-connection/snapshot acquisitions per +//! operation (not SQL rows), for direct authentication and one standalone GET per mode. +//! SQL work uses existing smallclaims sqlite::work trace counters (statements/VM steps). +//! Authentication work is thread-scoped; standalone GET work is process-global through the +//! receipt flush and can include background daemon SQL. No production code changes. +//! Current-head candidate diagnostics read the effective authority projection only; +//! the separate historical index DDL probe is not a current admission measurement. +//! Latencies use the real daemon's bound sockets, bearer middleware, grant lookup, +//! projection and durable approval consumption. + +use std::{collections::BTreeMap, path::PathBuf, sync::Arc, time::{Instant, SystemTime, UNIX_EPOCH}}; + +use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD}; +use fractal_daemon::{api::{self, AppState}, client::Client, model::ClaimInput, store::Store}; +use fractal_daemon::{AttentionListStore as _, EvidenceStore as _, SeatsStore as _}; +use fractal_daemon::api::client_v0::assistant::authorization::{ReadPayload, request_digest, signing_bytes, HEADER}; +use ring::{rand::SystemRandom, signature::{Ed25519KeyPair, KeyPair as _}}; +use serde_json::{Value, json}; +use tokio::sync::Barrier; + +const OWNER: &str = "person/bench-operator"; +const NODE: &str = "benchmark-member"; +const GRANTED: &str = "custom.client.assistant.v1.granted"; +const POLICY: &str = "custom.client.assistant.v1.policy"; +const REVOKED: &str = "custom.client.assistant.v1.revoked"; +const INDEX: &str = "claims_assistant_v1_principal_expiry_index"; +const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_expiry_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'),json_extract(body,'$.fields.expires_at_unix_ms'))"; +const A_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; +const PROJECTION_INDEX: &str = "assistant_grant_effective_active_index"; +const PATH: &str = "/v1/client/assistant/summary"; + +fn number(name: &str, default: usize) -> usize { + let value = std::env::var(name).map_or(default, |s| s.parse().expect("positive integer setting")); + assert!(value > 0, "{name} must be positive"); + value +} + +fn count(name: &str, default: usize) -> usize { + std::env::var(name).map_or(default, |s| s.parse().expect("nonnegative integer setting")) +} + +/// Bind source checkout/archive, build declaration and the actual running executable. +/// Embedded env values are Cargo-tracked inputs, not runtime overrides of old artifacts. +fn execution_identity() -> Value { + let required = |name: &str| std::env::var(name).unwrap_or_else(|_| panic!("set {name}; see harness instructions")); + let expected = required("ST_ADMISSION_EXPECT_REVISION"); + assert_eq!(expected.len(), 40, "use a full commit ID"); + assert!(expected.bytes().all(|byte| byte.is_ascii_hexdigit()), "use a full commit ID"); + let (Some(built_revision), Some(build_provenance)) = ( + option_env!("ST_ADMISSION_BUILD_REVISION"), + option_env!("ST_ADMISSION_BUILD_PROVENANCE"), + ) else { + panic!("opt-in measurement requires build revision and provenance; see harness instructions"); + }; + assert!(!build_provenance.trim().is_empty(), "build provenance must not be empty"); + assert_eq!(built_revision, expected, "the executable was built for a different source revision"); + let binary = std::env::current_exe().unwrap().canonicalize().unwrap(); + assert_eq!(binary, PathBuf::from(required("ST_ADMISSION_BINARY")).canonicalize().unwrap(), + "execute the explicitly selected Cargo artifact"); + let source_root = PathBuf::from(required("ST_ADMISSION_SOURCE_ROOT")).canonicalize().unwrap(); + let (git_head, source_revision, source_provenance) = if source_root.join(".git").exists() { + let git = |args: &[&str]| { + let output = std::process::Command::new("git").arg("-C").arg(&source_root).args(args).output().unwrap(); + assert!(output.status.success(), "git identity command failed"); + String::from_utf8(output.stdout).unwrap().trim().to_owned() + }; + assert_eq!(PathBuf::from(git(&["rev-parse", "--show-toplevel"])).canonicalize().unwrap(), source_root); + let head = git(&["rev-parse", "HEAD"]); + assert_eq!(head, expected, "source checkout and executable revision differ"); + let status = git(&["status", "--porcelain", "--untracked-files=no"]); + (Some(head.clone()), head, format!("git worktree; tracked changes:\n{status}")) + } else { + let revision = required("ST_ADMISSION_SOURCE_REVISION"); + let provenance = required("ST_ADMISSION_SOURCE_PROVENANCE"); + assert_eq!(revision, expected, "archive source and executable revision differ"); + assert!(!provenance.trim().is_empty(), "archive evidence must not be empty"); + (None, revision, provenance) + }; + use std::io::Read as _; + let mut executable = std::fs::File::open(&binary).unwrap(); + let mut hash = ring::digest::Context::new(&ring::digest::SHA256); + let mut buffer = [0_u8; 65_536]; + loop { + let bytes = executable.read(&mut buffer).unwrap(); + if bytes == 0 { break; } + hash.update(&buffer[..bytes]); + } + let sha256 = hex::encode(hash.finish().as_ref()); + json!({"git_rev_parse_head":git_head,"source_revision":source_revision, + "source_root":source_root,"source_provenance":source_provenance, + "binary_path":binary,"binary_sha256":sha256,"build_revision":built_revision, + "build_provenance":build_provenance, + "identity_limit":"build/archive provenance is explicitly supplied; SHA256 identifies executed bytes, not independent source attestation"}) +} + +fn value(response: Value) -> Value { + response.get("value").cloned().unwrap_or(response) +} + +fn key() -> Ed25519KeyPair { + let encoded = Ed25519KeyPair::generate_pkcs8(&SystemRandom::new()).unwrap(); + Ed25519KeyPair::from_pkcs8(encoded.as_ref()).unwrap() +} + +async fn begin(owner: &Client, mode: &str) -> Value { + value(owner.post("/v1/client/pairings", &json!({ + "api_version":"st3.client.v0", "device_name":"Admission measurement", + "assistant_id":"assistant/chatgpt", "scopes":["read.assistant.summary","read.assistant.attention","read.assistant.missions","read.assistant.agents"], + "expires_in_seconds":3600, "disclosure_consent":true, + "consent_evidence":"Disposable synthetic benchmark owner consent", "minimal_read_mode":mode, + })).await.unwrap()) +} + +async fn complete(http: &reqwest::Client, base: &str, challenge: &Value) -> Value { + let id = challenge["pairing_id"].as_str().unwrap().trim_start_matches("pairing/"); + let response = http.post(format!("{base}/v1/client/pairings/{id}/complete")) + .json(&json!({"api_version":"st3.client.v0", "code":challenge["code"], + "device_public_key":"BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc", "key_storage":"software"})) + .send().await.unwrap(); + let status = response.status(); + let body: Value = response.json().await.unwrap(); + assert!(status.is_success(), "completion {status}: {body}"); + value(body) +} + +fn proof(paired: &Value, signer: &Ed25519KeyPair, sequence: usize) -> String { + let parameters = BTreeMap::new(); + let payload = ReadPayload { + issuer:"scg/admission-bench".into(), identity:"chatgpt".into(), assistant_id:"assistant/chatgpt".into(), + grant_id:paired["grant"]["id"].as_str().unwrap().into(), + policy_revision:paired["grant"]["policy_revision"].as_u64().unwrap(), key_id:"approval-key/admission-bench".into(), + approval_id:format!("approval/admission-{sequence}"), execution_id:format!("execution/admission-{sequence}"), + projection:"summary".into(), max_response_bytes:4096, + request_digest:request_digest(PATH, ¶meters).unwrap(), parameters, + expires_at_unix_ms:u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap() + 60_000, + nonce:uuid::Uuid::new_v4().to_string(), + }; + let signature = URL_SAFE_NO_PAD.encode(signer.sign(signing_bytes(&payload).unwrap().as_bytes()).as_ref()); + URL_SAFE_NO_PAD.encode(serde_json::to_vec(&json!({"payload":payload,"signature":signature})).unwrap()) +} + +fn explain(connection: &rusqlite::Connection, query: &str, parameters: &[&dyn rusqlite::ToSql]) -> Vec { + let mut statement = connection.prepare(&format!("EXPLAIN QUERY PLAN {query}")).unwrap(); + let mut rows = statement.query(parameters).unwrap(); + let mut plan = Vec::new(); + while let Some(row) = rows.next().unwrap() { plan.push(row.get::<_, String>(3).unwrap()); } + plan +} + +fn p95(samples: &mut [f64]) -> Option { + samples.sort_by(f64::total_cmp); + (!samples.is_empty()).then(|| samples[(samples.len() * 95).div_ceil(100) - 1]) +} + +fn sql_work(work: smallclaims::sqlite::work::SqliteWork) -> Value { + assert!(work.statements > 0, "SQL work instrumentation must be enabled"); + json!({"statements":work.statements,"vm_steps":work.vm_steps, + "fullscan_steps":work.fullscan_steps,"sorts":work.sorts,"autoindex_rows":work.autoindex_rows}) +} + +fn profile_lines(path: &std::path::Path) -> usize { + std::fs::read_to_string(path).map_or(0, |log| log.lines().count()) +} + +/// The read acquisitions of the single `label` operation recorded after line `from`. +fn profile_reads(path: &std::path::Path, from: usize, label: &str) -> u64 { + let log = std::fs::read_to_string(path).expect("profile slow.jsonl must be readable"); + let rows = log.lines().skip(from).map(|line| serde_json::from_str::(line).unwrap()) + .filter(|row| row["label"] == label).collect::>(); + assert_eq!(rows.len(), 1, "expected exactly one new {label} profile row; set ST3_PROFILE_SLOW_MS=0"); + rows[0]["read_acquisitions"].as_u64().expect("profile rows report read_acquisitions") +} + +// Real signed membership and replication, outside measured requests. Merely +// copying origin text would not exercise the authentication provenance check. +fn foreign_same_profile(store: &Store, anchor: Arc, template: &Value, count: usize, active: &[(String, Value)], overlays: usize) { + let fleet = super::super::daemon_bench::FLEET; + store.pin_fleet_anchor(anchor.public()).unwrap(); + store.set_member_key(Some(anchor.clone())).unwrap(); + store.admit_fleet_anchor(fleet, anchor.public(), "listening").unwrap(); + let peer = Store::open_memory("benchmark-peer").unwrap(); + peer.bind_fleet(fleet).unwrap(); + let key = Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0); + peer.pin_fleet_anchor(anchor.public()).unwrap(); + peer.set_member_key(Some(key.clone())).unwrap(); + store.append_claim(&ClaimInput { + subject:"host/benchmark-peer".into(), kind:"fleet.member-admitted".into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(json!({ + "fleet_id":fleet,"member_key":key.public(),"via":"invite","mode":"listening" + })).unwrap(), evidence:vec![], expected_subject:None, idempotency_key:None, + }).unwrap(); + let sync = |from: &Store, to: &Store| { + let exchange = from.export_replication_exchange_answering( + fleet, &to.replication_inventory().unwrap(), &to.replication_signature_requests().unwrap(), + ).unwrap(); + to.receive_replication_exchange(from.origin(), fleet, &exchange).unwrap(); + to.validate_replication_backlog().unwrap(); + to.project_replication_backlog().unwrap(); + }; + sync(store, &peer); + let mut ids = Vec::new(); + for row in 0..count { + let id = format!("{:024x}", row + 1); + let mut fields = template.clone(); + fields["grant_id"] = json!(id); + fields["session_actor"] = json!(format!("assistant/chatgpt/session/{id}")); + fields["expires_at_unix_ms"] = json!(u64::MAX); + fields["credential_hash"] = json!(hex::encode(ring::digest::digest(&ring::digest::SHA256, id.as_bytes()).as_ref())); + let grant = peer.append_claim(&ClaimInput { + subject:format!("custom/client/assistant-v1-{id}"), kind:GRANTED.into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(fields).unwrap(), + evidence:vec![], expected_subject:None, idempotency_key:None, + }).unwrap(); + ids.push(grant.id); + } + for (subject, template) in active { + for row in 0..overlays { + let mut fields = template.clone(); + fields["expires_at_unix_ms"] = json!(1); + fields["policy_revision"] = json!(row + 100); + let overlay = peer.append_claim(&ClaimInput { + subject:subject.clone(), kind:if row % 2 == 0 { POLICY } else { REVOKED }.into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(fields).unwrap(), + evidence:vec![], expected_subject:None, idempotency_key:None, + }).unwrap(); + ids.push(overlay.id); + } + } + // Exchanges are cut to a body budget, so overlay histories need several rounds. + peer.seal_local_batches().unwrap(); + for _ in 0..256 { + sync(&peer, store); + if ids.iter().all(|id| revision_api::verified_writer(store, id)) { return; } + } + panic!("the foreign-grant scenario must exercise verified provenance"); +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 8)] +async fn authenticated_get_during_pairing() { + let Ok(variant) = std::env::var("ST_ADMISSION_VARIANT") else { return }; + assert!(matches!(variant.as_str(), "baseline" | "indexed")); + let identity = execution_identity(); + assert_eq!(variant, revision_api::VARIANT, "scenario variant must match the compiled revision API"); + let counts_only = std::env::var_os("ST_ADMISSION_READ_COUNTS_ONLY").is_some(); + assert!(counts_only || fractal_daemon::test_support::optimized_build(), "use --release"); + assert_eq!(std::env::var("ST3_PROFILE_SLOW_MS").as_deref(), Ok("0"), + "set ST3_PROFILE_SLOW_MS=0 to capture every measured operation"); + let profile_log = PathBuf::from(std::env::var_os("ST3_PROFILE_DIR") + .expect("set a fresh ST3_PROFILE_DIR for each revision")).join("slow.jsonl"); + smallclaims::profile::init_from_env(); + assert!(smallclaims::profile::enabled(), "profiling must initialize before Store::open"); + let indexed = variant == "indexed"; + let history = number("ST_ADMISSION_HISTORY", 10_000); + let policy_renewals = count("ST_ADMISSION_RENEWALS", 3); + let invalid_history_ids = std::env::var_os("ST_ADMISSION_INVALID_HISTORY_IDS").is_some(); + let samples = if counts_only { 0 } else { number("ST_ADMISSION_SAMPLES", 200) }; + let foreign_active = count("ST_ADMISSION_FOREIGN_ACTIVE", 0); + let overlays = count("ST_ADMISSION_WRONG_ORIGIN_OVERLAYS", 1000); + let local_active = number("ST_ADMISSION_LOCAL_ACTIVE", 2); + assert!(local_active >= 2, "the fixture measures two distinct read modes"); + if variant == "baseline" { + assert!(counts_only && foreign_active == 0 && overlays == 0, + "base requires READ_COUNTS_ONLY=1, FOREIGN_ACTIVE=0, WRONG_ORIGIN_OVERLAYS=0"); + } + let root = tempfile::tempdir().unwrap(); + let database = root.path().join("admission.sqlite"); + let store = Arc::new(Store::open(&database, NODE).unwrap()); + store.bind_fleet(super::super::daemon_bench::FLEET).unwrap(); + let node_key = Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0); + store.set_node_key(node_key.clone()).unwrap(); + let state = AppState { + seat_admission:Default::default(), owning_person:Some(OWNER.into()), store:store.clone(), + notify:Arc::new(tokio::sync::Notify::new()), event_notify:tokio::sync::watch::channel(0).0, + node:NODE.into(), state_dir:root.path().into(), pty_root:root.path().join("pty"), pty_binary:PathBuf::from("pty"), + fleet_id:None, configured_peers:vec![], client_relay:None, native_session_home:None, + planner_default:Default::default(), harness_question_sink:None, assistant_receipts:Default::default(), private_notes:Default::default(), + }; + api::start_operation_report(&state); + // Match run_up/daemon_load: the generic lists do not own the independent + // attention/summary and agent-roster publication workers. + let mut roster_publications = store.subscribe_agent_roster(); + let mut attention_publications = store.subscribe_attention_list(); + api::start_agent_roster(&state); + api::start_attention_list(&state); + api::start_published_lists(&state); + // Observe the workers' real publication watches, not an HTTP retry or a + // synchronous test-only fold. Subscribe before starting to avoid lost wakes. + roster_publications.wait_for(|_| store.published_agent_roster(u64::MAX, false).is_some()) + .await.expect("the daemon publishes its initial agent roster"); + attention_publications.wait_for(|_| store.published_attention_list().is_some()) + .await.expect("the daemon publishes its initial attention view"); + let socket = root.path().join("owner.sock"); + let reserved = api::reserve_unix_socket(&socket, None).await.unwrap(); + let (ready_tx, ready_rx) = tokio::sync::oneshot::channel(); + let local_app = api::router(state.clone()); + let local = tokio::spawn(async move { + api::serve_reserved_unix_with_ready(reserved, local_app, None, None, || { ready_tx.send(()).unwrap(); }).await.unwrap(); + }); + ready_rx.await.unwrap(); + let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); + let base = format!("http://{}", listener.local_addr().unwrap()); + let fabric_app = api::fabric_router(state.clone()); + let fabric = tokio::spawn(async move { axum::serve(listener, fabric_app).await.unwrap(); }); + let owner = Client::unix_as(&socket, OWNER).unwrap(); + let http = reqwest::Client::builder().no_proxy().build().unwrap(); + let signer = key(); + let mut sessions = Vec::new(); + for mode in ["approval-once", "caller-bound-allow"] { + let mut paired = complete(&http, &base, &begin(&owner, mode).await).await; + if mode == "approval-once" { + let id = paired["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/"); + let trust = value(owner.post(&format!("/v1/client/assistant/grants/{id}/read-trust"), &json!({ + "api_version":"st3.client.v0", "issuer":"scg/admission-bench", "key_id":"approval-key/admission-bench", + "attestor_public_key":URL_SAFE_NO_PAD.encode(signer.public_key().as_ref()), + "shim_public_key":URL_SAFE_NO_PAD.encode(key().public_key().as_ref()), + "default_response_bytes":4096, "max_response_bytes":16_384, + })).await.unwrap()); + paired["grant"] = trust; + } + sessions.push((mode, paired)); + } + let mut extra_sessions = Vec::new(); + for _ in 2..local_active { + extra_sessions.push(complete(&http, &base, &begin(&owner, "caller-bound-allow").await).await); + } + // Synthetic expired grants retain valid production field shapes, native Store envelopes, + // origin/actor and per-subject indexes. They are never service-profile fixtures and never + // authorize a request. Grant history is deliberately nonempty for BOTH principals. + let template_subject = format!("custom/client/assistant-v1-{}", sessions[0].1["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/")); + let template = store.claims_for_subject_kind_at(&template_subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); + let active = sessions.iter().map(|(_, paired)| paired).chain(extra_sessions.iter()).map(|paired| { + let subject = format!("custom/client/assistant-v1-{}", paired["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/")); + let grant = store.claims_for_subject_kind_at(&subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); + (subject, grant.body["fields"].clone()) + }).collect::>(); + if foreign_active > 0 || overlays > 0 { + foreign_same_profile(&store, node_key, &template.body["fields"], foreign_active, &active, overlays); + } + let fixture_store = store.clone(); + tokio::task::spawn_blocking(move || { + for principal in ["assistant/chatgpt", "assistant/mcp"] { + for row in 0..history { + let id = if invalid_history_ids { + format!("history-{}-{row}", principal.trim_start_matches("assistant/")) + } else { + format!("{:024x}", row * 2 + usize::from(principal == "assistant/mcp")) + }; + let mut fields = template.body["fields"].clone(); + fields["principal"] = json!(principal); + fields["grant_id"] = json!(format!("assistant-grant/{id}")); + fields["session_actor"] = json!(format!("{principal}/session/assistant-grant/{id}")); + fields["expires_at_unix_ms"] = json!(1); + fields["credential_hash"] = json!(hex::encode(ring::digest::digest(&ring::digest::SHA256, id.as_bytes()).as_ref())); + let subject = format!("custom/client/assistant-v1-{id}"); + fixture_store.append_claim(&ClaimInput { subject:subject.clone(), kind:GRANTED.into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(fields.clone()).unwrap(), evidence:vec![], expected_subject:None, idempotency_key:None }).unwrap(); + for revision in 0..policy_renewals { + fields["policy_revision"] = json!(revision + 2); + fields["expires_at_unix_ms"] = json!(revision + 2); + fixture_store.append_claim(&ClaimInput { subject:subject.clone(), kind:POLICY.into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(fields.clone()).unwrap(), + evidence:vec![], expected_subject:None, idempotency_key:None }).unwrap(); + } + } + } + }).await.unwrap(); + let connection = rusqlite::Connection::open(&database).unwrap(); + let candidate_query = revision_api::candidate_query(); + let query = candidate_query.as_ref().map_or(A_QUERY, |(query, _)| *query); + let after = if counts_only { + Vec::new() + } else if let Some((query, expiry)) = &candidate_query { + let plan = explain(&connection, query, rusqlite::params![ + "assistant/chatgpt", OWNER, expiry, Option::::None, Option::::None + ]); + assert!(plan.iter().any(|line| line.contains(PROJECTION_INDEX)), "{plan:?}"); + assert!(!plan.iter().any(|line| line.contains("claims")), "{plan:?}"); + plan + } else { + explain(&connection, A_QUERY, rusqlite::params![GRANTED, "assistant/chatgpt"]) + }; + let total_rows: u64 = connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); + let mut principal_rows = BTreeMap::new(); + for principal in ["assistant/chatgpt", "assistant/mcp"] { + let count: u64 = connection.query_row("SELECT count(*) FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2", rusqlite::params![GRANTED,principal], |r| r.get(0)).unwrap(); + principal_rows.insert(principal, count); + } + // Isolate the production effective-authority query from provenance and locks. + // Diagnostic work stays outside HTTP samples; no raw-history admission alias. + let mut diagnostics = Vec::new(); + for _ in 0..8 { + let candidate = candidate_query.as_ref().filter(|_| !counts_only).map(|(query, expiry)| { + let started = Instant::now(); + let mut statement = connection.prepare(query).unwrap(); + let grant_records = statement.query_map(rusqlite::params![ + "assistant/chatgpt", OWNER, expiry, Option::::None, Option::::None + ], |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); + // This independent diagnostic connection is not a traced Store connection. + let status = |counter| u64::try_from(statement.get_status(counter)).unwrap(); + let work = smallclaims::sqlite::work::SqliteWork { + statements: 1, + vm_steps: status(rusqlite::StatementStatus::VmStep), + fullscan_steps: status(rusqlite::StatementStatus::FullscanStep), + sorts: status(rusqlite::StatementStatus::Sort), + autoindex_rows: status(rusqlite::StatementStatus::AutoIndex), + }; + assert_eq!(grant_records.len(), local_active + foreign_active, + "expired history and wrong-origin overlays must not change active N"); + assert_eq!(work.fullscan_steps, 0, "candidate reads must not scan history"); + assert!(work.vm_steps <= 512 + 128 * u64::try_from(local_active + foreign_active).unwrap(), + "candidate VM work must scale with active N, not expired history or overlay floods: {work:?}"); + for record in &grant_records { + let _: fractal_daemon::model::ClaimRecord = serde_json::from_str(record).unwrap(); + } + (grant_records.len(), started.elapsed().as_secs_f64() * 1000.0, sql_work(work)) + }); + let credential = sessions[0].1["credential"].as_str().unwrap(); + let digest = hex::encode(ring::digest::digest(&ring::digest::SHA256, credential.as_bytes()).as_ref()); + let profile_from = profile_lines(&profile_log); + let started = Instant::now(); + let authentication_profile = smallclaims::profile::Op::start("admission-bench/authenticate", None).unwrap(); + let entered = authentication_profile.enter(); + let work_scope = smallclaims::sqlite::work::SqliteWorkScope::start(); + assert!(api::client_v0::external_grants::authenticate(&state, &digest, "http").unwrap().is_some()); + let authentication_sql_work = sql_work(work_scope.finish()); + drop(entered); + authentication_profile.finish(); + let direct_auth_ms = started.elapsed().as_secs_f64()*1000.0; + let authentication_read_acquisitions = profile_reads(&profile_log, profile_from, "admission-bench/authenticate"); + diagnostics.push(json!({"candidate_count":candidate.as_ref().map(|(count, _, _)| count), + "candidate_sql_ms":candidate.as_ref().map(|(_, ms, _)| ms), + "candidate_sql_work":candidate.as_ref().map(|(_, _, work)| work), + "direct_auth_ms":direct_auth_ms,"authentication_sql_work":authentication_sql_work, + "authentication_read_acquisitions":authentication_read_acquisitions})); + } + let inspected = store.claims_for_subject_kind_at(&template_subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); + let started = Instant::now(); + api::client_v0::external_grants::projection(&state, &inspected).unwrap(); + let legacy_projection_ms = started.elapsed().as_secs_f64()*1000.0; + let witness_projection_ms = revision_api::witness_projection_ms(&state, &inspected); + let plan = after.clone(); + println!("ADMISSION_DIAGNOSTICS {}", json!({"plan":plan,"samples":diagnostics, + "legacy_projection_ms":legacy_projection_ms,"witness_projection_ms":witness_projection_ms})); + drop(connection); + api::wait_published_lists_at_least(&store, store.index().unwrap()).await.unwrap(); + let mut measurements = Vec::new(); + for (mode, paired) in sessions { + let credential = paired["credential"].as_str().unwrap(); + let mut get_ms = Vec::with_capacity(samples); + let mut completion_ms = Vec::with_capacity(samples); + // One unmeasured warm GET, with a distinct one-use proof. + let warm = http.get(format!("{base}{PATH}")).bearer_auth(credential); + let warm = if mode == "approval-once" { warm.header(HEADER, proof(&paired, &signer, samples + 1)) } else { warm }; + let response = warm.send().await.unwrap(); + assert!(response.status().is_success(), "warm GET: {}", response.text().await.unwrap()); + // A separate unpaired read work window avoids attributing pairing completion + // SQL to the GET. Global counters can still include background daemon work. + state.assistant_receipts.flush().await.unwrap(); + api::wait_published_lists_at_least(&store, store.index().unwrap()).await.unwrap(); + let measured_read = http.get(format!("{base}{PATH}")).bearer_auth(credential); + let measured_read = if mode == "approval-once" { + measured_read.header(HEADER, proof(&paired, &signer, samples + 2)) + } else { measured_read }; + let before_read = smallclaims::sqlite::work::total(); + let profile_from = profile_lines(&profile_log); + let response = measured_read.send().await.unwrap(); + let status = response.status(); + let body = response.bytes().await.unwrap(); + state.assistant_receipts.flush().await.unwrap(); + let standalone_read_sql_work = sql_work(smallclaims::sqlite::work::total() - before_read); + assert!(status.is_success(), "standalone GET {status}: {}", String::from_utf8_lossy(&body)); + let standalone_read_acquisitions = profile_reads(&profile_log, profile_from, &format!("GET {PATH}")); + for sequence in 0..samples { + let challenge = begin(&owner, mode).await; + let get = http.get(format!("{base}{PATH}")).bearer_auth(credential); + let get = if mode == "approval-once" { get.header(HEADER, proof(&paired, &signer, sequence)) } else { get }; + let barrier = Barrier::new(2); + let read = async { + barrier.wait().await; + let started = Instant::now(); + let response = get.send().await.unwrap(); + let status = response.status(); + let body = response.bytes().await.unwrap(); + let elapsed = started.elapsed().as_secs_f64() * 1000.0; + assert!(status.is_success(), "GET {status}: {}", String::from_utf8_lossy(&body)); + elapsed + }; + let pairing = async { + barrier.wait().await; + let started = Instant::now(); + let completed = complete(&http, &base, &challenge).await; + (started.elapsed().as_secs_f64() * 1000.0, completed) + }; + let (read_ms, (pair_ms, completed)) = tokio::join!(read, pairing); + get_ms.push(read_ms); + completion_ms.push(pair_ms); + // Keep live-grant count stable; revocation is owner HTTP, outside both samples. + let id = completed["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/"); + let _: Value = owner.post(&format!("/v1/client/assistant/grants/{id}/revoke"), &json!({})).await.unwrap(); + } + state.assistant_receipts.flush().await.unwrap(); + let get_p95 = p95(&mut get_ms); + let completion_p95 = p95(&mut completion_ms); + measurements.push(json!({"mode":mode,"get_samples":get_ms.len(),"completion_samples":completion_ms.len(), + "get_p95_ms":get_p95,"completion_p95_ms":completion_p95,"q39_budget_ms":100, + "q39_pass":get_p95.map(|p95| p95 <= 100.0), + "standalone_read_sql_work":standalone_read_sql_work, + "standalone_read_acquisitions":standalone_read_acquisitions, + "get_ms":get_ms,"completion_ms":completion_ms})); + } + let hardware = |program: &str, args: &[&str]| { + let output = std::process::Command::new(program).args(args).output().unwrap(); + assert!(output.status.success()); + String::from_utf8(output.stdout).unwrap() + }; + let final_connection = rusqlite::Connection::open(&database).unwrap(); + let final_rows: u64 = final_connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); + let report = json!({"variant":variant,"read_counts_only":counts_only,"revision_api":revision_api::REVISION, + "execution_identity":identity,"local_active_grants":local_active,"active_grants_n":local_active + foreign_active, + "hardware_uname":hardware("uname", &["-a"]), + "hardware_lscpu":hardware("lscpu", &["-J"]),"hardware_hostname":hardware("hostname", &[]), + "host_description":"Observed local benchmark host; no prescribed hardware identity", + "fixture_person_ids":[OWNER],"verified_foreign_same_profile_active_grants":foreign_active, + "history_grants_per_principal":history,"initial_total_claim_rows":total_rows,"initial_granted_rows_by_principal":principal_rows, + "policy_renewals_per_expired_grant":policy_renewals, + "invalid_expired_history_ids":invalid_history_ids, + "wrong_origin_overlays_per_active_grant":overlays, + "wrong_origin_overlay_active_grants":active.len(), + "sql_work_scope":{"authentication":"current-thread completed traced SQL statements", + "standalone_read":"process-global, unpaired HTTP GET through receipt flush; may include background daemon SQL", + "read_count_limit":"statement/VM work counters, not logical rows read or storage IO", + "read_acquisitions":"existing profile read_acquisitions: pooled read-connection/snapshot acquisitions per operation"}, + "final_total_claim_rows":final_rows,"admission_query":query, + "conflict_fold_diagnostics":diagnostics, + "legacy_projection_ms":legacy_projection_ms,"witness_projection_ms":witness_projection_ms, + "explain_with_index":after, + "measurements":measurements}); + println!("ADMISSION_MEASUREMENT {}", serde_json::to_string_pretty(&report).unwrap()); + if let Some(path) = std::env::var_os("ST_ADMISSION_REPORT") { std::fs::write(path, serde_json::to_vec_pretty(&report).unwrap()).unwrap(); } + local.abort(); + fabric.abort(); + if indexed && !counts_only { + assert!(report["measurements"].as_array().unwrap().iter().all(|row| row["q39_pass"] == true), "q39: authenticated GET p95 must be <=100ms; see report"); + } +} + +/// Synthetic large-store index build, independent of the HTTP latency fixture: +/// ```sh +/// ST_ADMISSION_INDEX_BUILD=1 "$ST_ADMISSION_BINARY" daemon_cost::assistant_admission::synthetic_large_store_index_build --exact --nocapture --test-threads=1 +/// ``` +/// ST_ADMISSION_INDEX_ROWS defaults to 1,000,000 total claims. ST_ADMISSION_INDEX_REPORT +/// optionally saves JSON. This explicitly historical claims-index measurement is +/// independent of the current effective-authority query. It measures CREATE DDL, +/// not full Store::open, cold-disk startup, admission, or signature verification. +/// Use the same identity-bound build/export commands above (including SOURCE_ROOT, +/// EXPECT_REVISION and BINARY). Every index report carries the same execution identity. +#[test] +fn synthetic_large_store_index_build() { + if std::env::var_os("ST_ADMISSION_INDEX_BUILD").is_none() { return; } + let identity = execution_identity(); + assert!(fractal_daemon::test_support::optimized_build(), "use --release"); + let rows = number("ST_ADMISSION_INDEX_ROWS", 1_000_000); + let root = tempfile::tempdir().unwrap(); + let database = root.path().join("synthetic-index.sqlite"); + let store = Store::open(&database, NODE).unwrap(); + // Obtain a real Store-authored envelope and the real migrated schema. The SQL copies + // below are intentionally synthetic, not independently signed or admission-authoritative. + // Never reopen this fixture as a source of replicated/authenticated claims. + let template = store.append_claim(&ClaimInput { + subject:"custom/admission-index/template".into(), + kind:"custom.admission-index.fixture".into(), actor:Some(OWNER.into()), + fields:serde_json::from_value(json!({"principal":"assistant/chatgpt", + "expires_at_unix_ms":1,"fixture_payload":"synthetic large-store index build only"})).unwrap(), + evidence:vec![], expected_subject:None, idempotency_key:None, + }).unwrap(); + drop(store); + let mut connection = rusqlite::Connection::open(&database).unwrap(); + // Native claims triggers retain their real digest implementation during the + // synthetic population, just as on production/checkpoint writer connections. + smallclaims::store::configure_projection_writer(&connection).unwrap(); + connection.execute_batch("DROP INDEX IF EXISTS claims_assistant_v1_principal_expiry_index").unwrap(); + // Copy every native required column rather than depending on a second claims schema. + // The native autoincrement store_index, claim ID and subject must remain unique. + let columns = { + let mut statement = connection.prepare("PRAGMA table_info(claims)").unwrap(); + statement.query_map([], |row| row.get::<_, String>(1)).unwrap() + .collect::, _>>().unwrap() + }; + let quote = |name: &str| format!("\"{}\"", name.replace('"', "\"\"")); + let copied = columns.iter().filter(|name| name.as_str() != "store_index").collect::>(); + let destinations = copied.iter().map(|name| quote(name)).collect::>().join(","); + let expressions = copied.iter().map(|name| match name.as_str() { + "id" => "'synthetic-index-claim/' || sequence.n".to_owned(), + "subject" => "'custom/admission-index/row-' || sequence.n".to_owned(), + "kind" => format!("'{GRANTED}'"), + "body" => "json_set(template.body,'$.subject','custom/admission-index/row-' || sequence.n,\ + '$.kind','custom.client.assistant.v1.granted','$.fields.principal',\ + CASE WHEN sequence.n % 2=0 THEN 'assistant/chatgpt' ELSE 'assistant/mcp' END)".to_owned(), + _ => format!("template.{}", quote(name)), + }).collect::>().join(","); + let transaction = connection.transaction().unwrap(); + if rows > 1 { + transaction.execute(&format!( + "WITH RECURSIVE sequence(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM sequence WHERE n Option<(&'static str, String)> { None } +/// pub fn verified_writer(_: &Store, _: &str) -> bool { +/// panic!("origin/main has no provenance check; use FOREIGN_ACTIVE=0 and WRONG_ORIGIN_OVERLAYS=0") +/// } +/// pub fn witness_projection_ms(_: &AppState, _: &fractal_daemon::model::ClaimRecord) -> Option { None } +/// ``` +mod revision_api { + use super::*; + pub const REVISION: &str = "fixed-head"; + pub const VARIANT: &str = "indexed"; + pub fn candidate_query() -> Option<(&'static str, String)> { + let now = u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap(); + Some((smallclaims::store::assistant_grant_authority::CANDIDATES_QUERY, + smallclaims::store::assistant_grant_authority::expiry_key(now))) + } + pub fn verified_writer(store: &Store, id: &str) -> bool { + store.claim_has_authenticated_member_writer(id).unwrap() + } + pub fn witness_projection_ms(state: &AppState, inspected: &fractal_daemon::model::ClaimRecord) -> Option { + let started = Instant::now(); + api::client_v0::external_grants::projection_with_witness(state, inspected).unwrap(); + Some(started.elapsed().as_secs_f64() * 1000.0) + } +} diff --git a/crates/fractal/tests/fleet.rs b/crates/fractal/tests/fleet.rs index 1aea543766c..ab6e5f74378 100644 --- a/crates/fractal/tests/fleet.rs +++ b/crates/fractal/tests/fleet.rs @@ -3634,6 +3634,19 @@ fn fleet_workflows_have_no_path_filter() { "previous_release_replicates_with_new_members_and_preserves_history_on_upgrade" ) ); + assert!( + stages.contains( + "fleet::service_grants::previous_release_authorizes_and_revokes_after_authority_projection_rollback" + ), + "fleet compatibility must exercise baseline rollback after authority projection backfill" + ); + assert!( + stages.contains( + "fleet::service_grants::authority_projection_resumes_after_daemon_is_killed_with_committed_partial_backfill" + ), + "fleet compatibility must exercise abrupt daemon death with an incomplete authority projection" + ); + assert!(stages.contains("test result: ok. 11 passed")); // The optional macOS job lives in macos.yml so label events cannot restart this gate. assert!( !compat.to_ascii_lowercase().contains("macos-"), diff --git a/crates/fractal/tests/fleet/service_grants.rs b/crates/fractal/tests/fleet/service_grants.rs index 56b33485da4..94b4a97a0f9 100644 --- a/crates/fractal/tests/fleet/service_grants.rs +++ b/crates/fractal/tests/fleet/service_grants.rs @@ -58,7 +58,11 @@ fn seed(node: &Node, number: u8, profile: &str, principal: &str, scope: &str, let policy = append(node, &id, POLICY, fields, Some(&granted)); let mut claims = BTreeSet::from([granted, policy.clone()]); if revoked { - claims.insert(append(node, &id, REVOKED, json!({}), Some(&policy))); + // Same shape as the owner revoke route: only an authoritative revocation counts. + claims.insert(append(node, &id, REVOKED, json!({ + "version": 1, "grant_id": id, "principal": principal, "issuer": PERSON, + "transport": "fixture", "timestamp": "2026-01-01T00:00:00Z", "outcome": "revoked" + }), Some(&policy))); } Grant { id, credential, claims } } @@ -79,11 +83,31 @@ async fn auth_response(node: &Node, grant: &Grant) -> (u16, String) { } async fn assert_auth(node: &Node, grant: &Grant, accepted: bool) { + assert_status(node, grant, if accepted { 400 } else { 403 }).await; +} + +async fn assert_status(node: &Node, grant: &Grant, expected: u16) { let (status, body) = auth_response(node, grant).await; - assert_eq!(status, if accepted { 400 } else { 403 }, + assert_eq!(status, expected, "{} grant {}: {body}\n{}", node.name, grant.id, node.logs()); } +// With the counterexample, assistant grant 4 (index 3) and service grant 7 (index 6) +// are active, well-formed opposite-profile grants for assistant/chatgpt. The +// candidate suspends both: it refuses with the conflict (409 grant-profile-conflict) +// before the service-profile refusal (403), so grant 7 answers 409, not 403. +// Grant 3 (index 2) has a non-assistant scope, +// so it is malformed for conflicts and stays a plain 403 service refusal. +fn candidate_counterexample_status(index: usize) -> u16 { + if index == 3 || index == 6 { 409 } else { 403 } +} + +async fn assert_candidate_counterexample(node: &Node, grants: &[Grant]) { + for (index, grant) in grants.iter().enumerate() { + assert_status(node, grant, candidate_counterexample_status(index)).await; + } +} + async fn assert_retained(node: &Node, grants: &[Grant]) { let ids: BTreeSet = node.claims().await.into_iter() .map(|claim| claim["id"].as_str().unwrap().to_owned()).collect(); @@ -171,9 +195,7 @@ async fn previous_release_refuses_plugin_service_grants_on_same_database_rollbac assert_candidate_issuance_grammar(&node).await; // Includes the unissuable profile-blind counterexample; candidate must refuse it. let grants = fixtures(&mut node, true).await; - for (index, grant) in grants.iter().enumerate() { - assert_auth(&node, grant, index == 3).await; - } + assert_candidate_counterexample(&node, &grants).await; let state = node.state_dir(); node.stop(); node.binary = old; @@ -233,12 +255,256 @@ async fn previous_release_refuses_plugin_service_grants_on_same_database_rollbac node.binary = PathBuf::from(st3()); node.start().await; assert_eq!(node.state_dir(), state); - for (index, grant) in grants.iter().enumerate() { - assert_auth(&node, grant, index == 3).await; - } + assert_candidate_counterexample(&node, &grants).await; assert_retained(&node, &grants).await; } +// Use the release's real issuance and policy routes: this history must predate the +// candidate's first Store::open, rather than being seeded by candidate store code. +async fn issue_with_policy(node: &Node, key: u8) -> Grant { + use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD}; + + let owner = Client::unix_as(node.socket(), PERSON).unwrap(); + let policy = json!({ + "api_version":"st3.client.v0", + "scopes":["read.assistant.summary", "read.assistant.attention", + "read.assistant.missions", "read.assistant.agents"], + "expires_in_seconds":3600, "minimal_read_mode":"approval-once", + "disclosure_consent":true, "consent_evidence":"Disposable rollback fixture owner consent" + }); + let mut begin = policy.clone(); + begin["assistant_id"] = json!("assistant/chatgpt"); + begin["device_name"] = json!(format!("rollback fixture {key}")); + let challenge: Value = owner.post("/v1/client/pairings", &begin).await.unwrap(); + let challenge = challenge.get("value").unwrap_or(&challenge); + let pairing = challenge["pairing_id"].as_str().unwrap().trim_start_matches("pairing/"); + let response = reqwest::Client::builder().unix_socket(node.socket()).build().unwrap() + .post(format!("http://localhost/v1/client/pairings/{pairing}/complete")) + .json(&json!({"api_version":"st3.client.v0", "code":challenge["code"], + "device_public_key":URL_SAFE_NO_PAD.encode([key; 32]), "key_storage":"software"})) + .send().await.unwrap(); + let status = response.status(); + let paired: Value = response.json().await.unwrap(); + assert_eq!(status.as_u16(), 200, "baseline assistant issuance: {paired}"); + let paired = paired.get("value").unwrap_or(&paired); + let id = paired["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/").to_owned(); + let changed: Value = owner.post( + &format!("/v1/client/assistant/grants/{id}/policy"), &policy, + ).await.unwrap(); + let changed = changed.get("value").unwrap_or(&changed); + assert_eq!(changed["policy_revision"], 2, "{changed}"); + let subject = format!("custom/client/assistant-v1-{id}"); + let claims = node.claims().await.into_iter() + .filter(|claim| claim["subject"] == subject) + .map(|claim| claim["id"].as_str().unwrap().to_owned()).collect(); + Grant { id, credential: paired["credential"].as_str().unwrap().to_owned(), claims } +} + +fn authority_history(node: &Node) -> Vec<(String, String)> { + let connection = rusqlite::Connection::open_with_flags( + node.state_dir().join("claims.sqlite3"), rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap(); + connection.prepare( + "SELECT id, body FROM claims WHERE kind IN (?1, ?2, ?3) ORDER BY id", + ).unwrap().query_map([GRANTED, POLICY, REVOKED], |row| { + Ok((row.get(0)?, row.get(1)?)) + }).unwrap().collect::>().unwrap() +} + +fn assert_authority_projection_ready(node: &Node) { + let version: String = rusqlite::Connection::open_with_flags( + node.state_dir().join("claims.sqlite3"), rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap().query_row( + "SELECT value FROM meta WHERE key='assistant_grant_authority_version'", + [], |row| row.get(0), + ).unwrap(); + assert_eq!(version, "1", "candidate must complete authority backfill before rollback"); +} + +fn authority_projection_snapshot(connection: &rusqlite::Connection) -> (Vec, Vec) { + let authority = connection.prepare( + "SELECT json_array(claim_id,base_claim_id,grant_subject,kind,origin,actor,principal,profile, + expires_at,store_index,credential_hash,record) + FROM assistant_grant_authority ORDER BY claim_id,base_claim_id", + ).unwrap().query_map([], |row| row.get(0)).unwrap() + .collect::>>().unwrap(); + let effective = connection.prepare( + "SELECT json_array(claim_id,grant_subject,principal,owner,profile,expires_at,revoked,grant_record) + FROM assistant_grant_effective ORDER BY claim_id", + ).unwrap().query_map([], |row| row.get(0)).unwrap() + .collect::>>().unwrap(); + (authority, effective) +} + +fn authority_backfill_progress(connection: &rusqlite::Connection) -> (u64, bool) { + connection.query_row( + "SELECT COALESCE((SELECT CAST(value AS INTEGER) FROM meta WHERE key=?1),0), + EXISTS(SELECT 1 FROM meta WHERE key='assistant_grant_authority_version')", + [format!("assistant_grant_authority_cursor/{GRANTED}")], + |row| Ok((row.get(0)?, row.get(1)?)), + ).unwrap() +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore = "needs ST3_COMPAT_BIN: the pinned previous published release"] +async fn authority_projection_resumes_after_daemon_is_killed_with_committed_partial_backfill() { + use smallclaims::store::assistant_grant_authority as authority; + + if fractal_daemon::test_support::supervise_test() { return; } + let root = tempfile::tempdir().unwrap(); + let mut node = Node::new(root.path(), "issuer"); + node.binary = compat_binary(); + node.start().await; + let active = issue_with_policy(&node, 7).await; + let revoked = issue_with_policy(&node, 8).await; + let owner = Client::unix_as(node.socket(), PERSON).unwrap(); + let _: Value = owner.post( + &format!("/v1/client/assistant/grants/{}/revoke", revoked.id), &json!({}), + ).await.unwrap(); + let history = authority_history(&node); + assert_eq!(history.len(), 5); + node.stop(); + + let database = node.state_dir().join("claims.sqlite3"); + let mut connection = rusqlite::Connection::open(&database).unwrap(); + fractal_daemon::store::configure_projection_writer(&connection).unwrap(); + authority::install(&connection, &node.name).unwrap(); + let reference_path = root.path().join("uninterrupted.sqlite3"); + connection.execute("VACUUM INTO ?1", [reference_path.to_str().unwrap()]).unwrap(); + let mut reference = rusqlite::Connection::open(&reference_path).unwrap(); + fractal_daemon::store::configure_projection_writer(&reference).unwrap(); + loop { + let transaction = reference.transaction().unwrap(); + let done = authority::backfill_slice(&transaction, Duration::from_secs(2)).unwrap(); + transaction.commit().unwrap(); + if done { break; } + } + let expected = authority_projection_snapshot(&reference); + assert!(expected.0.is_empty(), "pre-marker Legacy grants lack authenticated writer provenance"); + assert!(expected.1.is_empty()); + drop(reference); + + // Commit one real backfill step rather than making the fixture's size depend on + // machine speed. The writer fence holds startup at this incomplete migration, + // so an actual process kill cannot race a fast daemon finishing all five rows. + let transaction = connection.transaction().unwrap(); + assert!(!authority::backfill_slice(&transaction, Duration::ZERO).unwrap()); + transaction.commit().unwrap(); + let partial = authority_backfill_progress(&connection); + assert!(partial.0 > 0, "must kill with durable forward progress"); + assert!(!partial.1, "the committed projection must still be incomplete"); + assert!(authority_projection_snapshot(&connection).0.is_empty(), + "a partial cursor must not turn ambiguous Legacy evidence into authority"); + let blocker = connection.transaction_with_behavior(rusqlite::TransactionBehavior::Immediate).unwrap(); + node.binary = PathBuf::from(st3()); + let pty = node.root.join("bin/pty"); + let mut daemon = DaemonProcess::spawn_isolated( + node.command(&["up", "--pty-binary", pty.to_str().unwrap(), "--web-listen", "off"]), + fs::File::create(node.root.join("daemon.log")).unwrap(), + fs::File::create(node.root.join("daemon.stderr.log")).unwrap(), + ).unwrap(); + let deadline = Instant::now() + Duration::from_secs(30); + loop { + assert!(daemon.try_wait().unwrap().is_none(), "candidate exited before interrupted startup:\n{}", node.logs()); + // Startup owns the directory fence before opening/migrating the store. + if fractal_daemon::node_identity::lock_directory(&node.state_dir()).is_err() { + break; + } + assert!(Instant::now() < deadline, "candidate did not acquire its startup state fence:\n{}", node.logs()); + tokio::time::sleep(Duration::from_millis(10)).await; + } + assert_eq!(authority_backfill_progress(&blocker), partial); + daemon.kill().unwrap(); + assert!(!daemon.wait().unwrap().success(), "the interrupted daemon must not exit gracefully"); + assert_eq!(authority_backfill_progress(&blocker), partial, "kill must retain the committed cursor"); + blocker.rollback().unwrap(); + drop(connection); + assert_eq!(authority_history(&node), history, "process kill must not alter raw evidence"); + + node.start().await; + wait_until("authority backfill becomes ready after daemon restart", 30, || async { + let reader = rusqlite::Connection::open_with_flags( + &database, rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap(); + authority_backfill_progress(&reader).1 + }).await; + assert_authority_projection_ready(&node); + let reader = rusqlite::Connection::open_with_flags( + &database, rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap(); + assert_eq!(authority_projection_snapshot(&reader), expected, + "restart must converge exactly to uninterrupted authority and effective rows"); + assert_auth(&node, &active, false).await; + assert_auth(&node, &revoked, false).await; + assert_eq!(authority_history(&node), history, "restart must preserve every raw claim body"); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore = "needs ST3_COMPAT_BIN: the pinned previous published release"] +async fn previous_release_authorizes_and_revokes_after_authority_projection_rollback() { + if fractal_daemon::test_support::supervise_test() { return; } + let root = tempfile::tempdir().unwrap(); + let mut node = Node::new(root.path(), "issuer"); + node.binary = compat_binary(); + node.start().await; + let active = issue_with_policy(&node, 7).await; + let revoked = issue_with_policy(&node, 8).await; + let owner = Client::unix_as(node.socket(), PERSON).unwrap(); + let _: Value = owner.post( + &format!("/v1/client/assistant/grants/{}/revoke", revoked.id), &json!({}), + ).await.unwrap(); + assert_auth(&node, &active, true).await; + assert_auth(&node, &revoked, false).await; + let history = authority_history(&node); + assert_eq!(history.len(), 5, "two grants, two policy renewals and one revocation"); + let projection_exists: bool = rusqlite::Connection::open_with_flags( + node.state_dir().join("claims.sqlite3"), rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap().query_row( + "SELECT EXISTS(SELECT 1 FROM sqlite_schema WHERE type='table' AND name='assistant_grant_authority')", + [], |row| row.get(0), + ).unwrap(); + assert!(!projection_exists, "baseline history must predate authority projection initialization"); + let state = node.state_dir(); + + node.stop(); + node.binary = PathBuf::from(st3()); + node.start().await; + assert_eq!(node.state_dir(), state); + assert_authority_projection_ready(&node); + // The old standalone issuer had no member signature or local-append marker. + // The upgrade preserves evidence but requires its owner to re-issue. + assert_auth(&node, &active, false).await; + assert_auth(&node, &revoked, false).await; + assert_eq!(authority_history(&node), history, "backfill must not rewrite raw evidence"); + + node.stop(); + node.binary = compat_binary(); + node.start().await; + assert_eq!(node.state_dir(), state); + assert_auth(&node, &active, true).await; + assert_auth(&node, &revoked, false).await; + assert_eq!(authority_history(&node), history, "baseline must retain the backfilled history"); + let owner = Client::unix_as(node.socket(), PERSON).unwrap(); + let _: Value = owner.post( + &format!("/v1/client/assistant/grants/{}/revoke", active.id), &json!({}), + ).await.unwrap(); + assert_auth(&node, &active, false).await; + let after_revoke = authority_history(&node); + assert_eq!(after_revoke.len(), history.len() + 1); + for claim in &history { + assert!(after_revoke.contains(claim), "baseline revoke changed prior evidence"); + } + + node.stop(); + node.binary = PathBuf::from(st3()); + node.start().await; + assert_authority_projection_ready(&node); + assert_auth(&node, &active, false).await; + assert_auth(&node, &revoked, false).await; + assert_retained(&node, &[active, revoked]).await; + assert_eq!(authority_history(&node), after_revoke, "reopen must retain the baseline revoke"); +} + fn compat_binary() -> PathBuf { PathBuf::from(std::env::var("ST3_COMPAT_BIN").expect("ST3_COMPAT_BIN names the pinned baseline")) } @@ -249,6 +515,18 @@ async fn candidate_offline_service_fixtures_replicate_without_authorizing_creden mixed_pair(None, false).await; } +// Candidate-only reproduction of the rollback fixture, without a baseline binary. +#[tokio::test(flavor = "multi_thread")] +async fn candidate_suspends_the_offline_counterexample_profile_conflict() { + if fractal_daemon::test_support::supervise_test() { return; } + let root = tempfile::tempdir().unwrap(); + let mut node = Node::new(root.path(), "issuer"); + node.start().await; + let grants = fixtures(&mut node, true).await; + assert_candidate_counterexample(&node, &grants).await; + assert_retained(&node, &grants).await; +} + async fn assert_candidate_issuance_grammar(node: &Node) { let client = reqwest::Client::builder().unix_socket(node.socket()).build().unwrap(); let request = json!({"api_version":"st3.client.v0", "device_name":"fixture", diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index 9a53d54ab0b..140a43cf43e 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -43,6 +43,11 @@ pub use admitted::{AdmittedStore, STORE_DATABASE_FILES}; mod proof; pub mod prepared_envelope; +pub mod assistant_grant_authority; +#[cfg(test)] +mod assistant_grant_authority_tests; +#[cfg(test)] +mod assistant_grant_authority_bench; mod replica_record; use crate::operation_metadata::OperationMetadata; #[cfg(test)] @@ -885,6 +890,12 @@ pub struct Store { admission_schema_digest: std::sync::OnceLock, /// The membership last folded, and the `fleet_generation` it was folded at. pub membership_cache: Mutex>, + /// Request-only sealed folds, which may omit local batches not yet sealed. + /// Never used by the sealing path's `membership_cache` fast path. + sealed_membership_cache: Mutex>, + /// Last inherited generation whose applied window snapshot was checked. + /// Equal snapshots advance only this memory cache, never the writer. + assistant_grant_membership_observed_generation: AtomicI64, /// Where the scan for signatures missing on admitted envelopes stands. signature_backfill: Mutex, /// Read-only sealed view; never populated with the client's local-signer fallback. @@ -1265,6 +1276,14 @@ impl Store { readers.path == path && readers.shared_memory == shared_memory, "st database writer and read pool must use the same opened database path and mode" ); + assistant_grant_authority::install(&connection, &origin)?; + { + let transaction = connection.unchecked_transaction()?; + assistant_grant_authority::backfill_slice( + &transaction, std::time::Duration::from_secs(2), + )?; + transaction.commit()?; + } // Batch rowids are the sealing frontier. Checkpoint adoption can remove the highest // rows, so SQLite's default rowid allocator cannot be used: it reuses those keys and // leaves new local batches behind the frontier. Persist the allocation high water. @@ -1343,6 +1362,8 @@ impl Store { admission: Mutex::new(()), admission_schema_digest: std::sync::OnceLock::new(), membership_cache: Mutex::new(None), + sealed_membership_cache: Mutex::new(None), + assistant_grant_membership_observed_generation: AtomicI64::new(i64::MIN), fleet_authority: std::sync::OnceLock::new(), admitted_fleet_generation: AtomicI64::new(i64::MIN), signature_backfill: Mutex::default(), @@ -2175,7 +2196,16 @@ pub /* sqlite-large-value-flow: allow-for-now flow-h8ff255a3c271 owner=smallclai serde_json::to_string(predecessors)?, now.to_string(), ])?; - Ok(transaction.last_insert_rowid() as u64) + let store_index = transaction.last_insert_rowid() as u64; + if matches!(kind, assistant_grant_authority::GRANTED | assistant_grant_authority::POLICY | assistant_grant_authority::REVOKED) { + // This function is the local append boundary; replicated admission uses + // its own insert path and must never write this marker. + transaction.execute( + "INSERT INTO assistant_grant_local_appends(claim_id) VALUES(?1)", [id], + )?; + assistant_grant_authority::refresh_claim(transaction, id)?; + } + Ok(store_index) } /// The next sequence for a local batch: one past the writer's highest batch, including one a @@ -2646,8 +2676,13 @@ impl Store { { return Ok(membership.clone()); } - // Do not populate the sealing path's cache with a fold that can omit local batches. - fleet_membership_tx(&connection) + // Keep cold request folds separate: they can omit unsealed local batches, + // so publishing them into membership_cache would bypass the sealing path. + sealed_membership_tx( + &connection, + &mut self.sealed_membership_cache.lock() + .unwrap_or_else(PoisonError::into_inner), + ) }) } @@ -2949,6 +2984,96 @@ impl Store { Ok(false) } + /// Whether an accepted copy was signed by a keyed fleet member acting as its origin. + /// Requires a valid record in a validated or degraded envelope, a signature key authorized + /// for that writer's sequence, and a cryptographically valid signature in this store's + /// fleet/shard domain. Invalid sibling records do not disqualify a valid record in a + /// degraded envelope. Legacy and unkeyed writers do not authenticate provenance. Reads only sealed + /// membership; this query never seals local batches or scans the replication log. + pub fn claim_has_authenticated_member_writer(&self, claim_id: &str) -> Result { + Ok(self.authenticated_member_writer_claim_ids(&serde_json::to_string(&[claim_id])?)? + .contains(claim_id)) + } + + /// The requested claims with fully authenticated keyed-member envelope provenance. + /// Uses the same membership windows, record states, origin check and fleet/shard signature + /// domain as [`Self::claim_has_authenticated_member_writer`]. All claims share one read + /// snapshot and one sealed-membership lookup; identical envelope signatures are verified + /// at most once, including signatures shared by several claims or repeated input IDs. + pub fn claim_ids_with_authenticated_member_writers( + &self, + claim_ids: &[String], + ) -> Result> { + if claim_ids.is_empty() { + return Ok(BTreeSet::new()); + } + self.authenticated_member_writer_claim_ids(&serde_json::to_string(claim_ids)?) + } + + fn authenticated_member_writer_claim_ids(&self, claim_ids: &str) -> Result> { + self.read_snapshot(|_| { + let membership = self.fleet_membership_sealed()?; + let connection = self.readers.get(); + let Some(fleet_id) = self.signing_fleet_id(&connection)? else { + return Ok(BTreeSet::new()); + }; + let shard = fleet_meta(&connection, "shard_id")?; + let mut statement = connection.prepare_cached( + "SELECT records.claim_id, records.writer, records.sequence, records.envelope_hash, + signatures.member_key, signatures.signature + FROM replica_records AS records + JOIN claims ON claims.id=records.claim_id AND claims.origin=records.writer + JOIN replica_envelopes AS envelopes + USING (writer, sequence, envelope_hash) + JOIN replica_envelope_signatures AS signatures + USING (writer, sequence, envelope_hash) + WHERE records.claim_id IN (SELECT value FROM json_each(?1)) + AND records.state='valid' + AND envelopes.receipt_state IN ('validated', 'degraded')", + )?; + let rows = statement.query_map([claim_ids], |row| { + Ok(( + row.get::<_, String>(0)?, + ( + row.get::<_, String>(1)?, + row.get::<_, u64>(2)?, + row.get::<_, String>(3)?, + row.get::<_, String>(4)?, + row.get::<_, String>(5)?, + ), + )) + })?; + let mut authenticated = BTreeSet::new(); + let mut verified = BTreeMap::new(); + for row in rows { + let (claim_id, signature_identity) = row?; + if authenticated.contains(&claim_id) { + continue; + } + let valid = *verified.entry(signature_identity).or_insert_with_key(|identity| { + let (writer, sequence, hash, key, signature) = identity; + if !matches!( + membership.window(writer, *sequence), + crate::fleet::Window::Keyed(keys) if keys.contains(key) + ) { + return false; + } + #[cfg(test)] + membership_query_tests::SIGNATURE_VERIFICATIONS.with(|count| { + count.set(count.get() + 1); + }); + VerifiedEnvelopeSignature::verify( + shard.as_deref(), &fleet_id, writer, *sequence, hash, key, signature, + ).is_some() + }); + if valid { + authenticated.insert(claim_id); + } + } + Ok(authenticated) + }) + } + /// Envelopes this node admitted before it knew that their writer is keyed or that their /// incarnation had ended. Admission decisions are not revisited, so these stay admitted; @@ -3292,6 +3417,22 @@ fn fleet_generation(connection: &Connection) -> Result { .query_row(/* sqlite-large-value: allow-for-now lv-h339ecb1b2413 owner=smallclaims::store TODO=trace-statement-and-value-representation */ [], |row| row.get(0))?) } +// The caller holds one snapshot for both the generation read and membership fold. +fn sealed_membership_tx( + connection: &Connection, + cache: &mut Option<(i64, crate::fleet::Membership)>, +) -> Result { + let generation = fleet_generation(connection)?; + if let Some((cached_generation, membership)) = cache.as_ref() + && *cached_generation == generation + { + return Ok(membership.clone()); + } + let membership = fleet_membership_tx(connection)?; + *cache = Some((generation, membership.clone())); + Ok(membership) +} + // The caller holds a read snapshot. Unlike the client view this has no local signer; // Membership::fold and FleetView::from_membership use no clock or expiry state. fn sealed_fleet_view_tx( @@ -3587,7 +3728,7 @@ impl<'a> VerifiedEnvelopeSignature<'a> { } fn store(&self, transaction: &Transaction<'_>, now: &str) -> Result { - Ok(transaction + let inserted = transaction .prepare_cached( /* sqlite-large-value: allow-for-now lv-hece070718e6e owner=smallclaims::store TODO=chunk-or-reference-exact-wire-values */ "INSERT OR IGNORE INTO replica_envelope_signatures( writer, sequence, envelope_hash, member_key, signature, stored_at_unix_ms @@ -3600,7 +3741,8 @@ impl<'a> VerifiedEnvelopeSignature<'a> { self.member_key, self.signature, now - ])?) + ])?; + Ok(inserted) } } @@ -3626,6 +3768,7 @@ impl FleetAuthority for Store { fleet_generation(&self.readers.get()) } + fn fleet_membership(&self) -> Result { Store::fleet_membership(self) } @@ -7043,7 +7186,11 @@ impl Store { ); self.fleet_authority .set(authority) - .map_err(|_| anyhow::anyhow!("this shard already has a fleet authority")) + .map_err(|_| anyhow::anyhow!("this shard already has a fleet authority"))?; + // Generation numbers belong to their authority. Recheck the inherited + // snapshot even if it happens to equal the shard's former local number. + self.assistant_grant_membership_observed_generation.store(i64::MIN, Ordering::Release); + Ok(()) } /// The fleet this store's envelopes sign for: its authority's, for a shard. diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs new file mode 100644 index 00000000000..248163d461b --- /dev/null +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -0,0 +1,704 @@ +//! Incremental, authenticated external-grant authority. Raw claims remain evidence only. +use super::*; +use std::time::{Duration, Instant}; + +pub const GRANTED: &str = "custom.client.assistant.v1.granted"; +pub const POLICY: &str = "custom.client.assistant.v1.policy"; +pub const REVOKED: &str = "custom.client.assistant.v1.revoked"; +const VERSION: &str = "1"; +const KINDS: [&str; 3] = [GRANTED, POLICY, REVOKED]; +pub const CLAIMS_PER_SLICE: usize = 64; +pub const MEMBERSHIP_KEYS_PER_REFRESH: usize = 16; +const SCOPES: &[&str] = &[ + "read.assistant.summary", "read.assistant.attention", "read.assistant.missions", + "read.assistant.agents", "read.assistant.conversation", "read.assistant.terminal", + "write.assistant.messages", "write.assistant.custom-reply", "write.assistant.answers", +]; + +pub fn principal(fields: &Value) -> Option<&str> { + match fields.get("principal") { + None => Some("assistant/chatgpt"), + Some(value) => value.as_str().filter(|value| matches!(*value, "assistant/chatgpt" | "assistant/mcp")), + } +} +fn profile(fields: &Value) -> Option<&str> { + match fields.get("profile") { + None => Some("assistant"), + Some(value) => value.as_str().filter(|value| matches!(*value, "assistant" | "service")), + } +} +fn digest(value: &Value) -> bool { + value.as_str().is_some_and(|value| value.len() == 64 && value.bytes().all(|byte| byte.is_ascii_hexdigit())) +} +fn digest_only(fields: &Value) -> bool { + fields.get("credential").is_none() && fields.get("code").is_none() + && ["credential_hash", "code_hash"].iter().all(|key| fields.get(*key).is_none_or(digest)) +} +fn identity(claim: &ClaimRecord) -> bool { + let fields = &claim.body["fields"]; + let Some(id) = fields["grant_id"].as_str() else { return false; }; + let suffix = id.strip_prefix("assistant-grant/").unwrap_or(id); + fields.is_object() && principal(fields).is_some() && profile(fields).is_some() + && suffix.len() == 24 && suffix.bytes().all(|byte| byte.is_ascii_hexdigit()) + && claim.subject.strip_prefix("custom/client/assistant-v1-") == Some(suffix) + && claim.actor.as_deref().is_some_and(|actor| fields["issuer"].as_str() == Some(actor)) +} +fn policy_fields(claim: &ClaimRecord) -> bool { + let fields = &claim.body["fields"]; + identity(claim) && digest_only(fields) + && fields["session_actor"].as_str().and_then(|actor| + principal(fields).and_then(|principal| actor.strip_prefix(principal))) + .and_then(|suffix| suffix.strip_prefix("/session/")) == fields["grant_id"].as_str() + && matches!(fields["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) + && fields["disclosure_consent"] == true + && fields["expires_at_unix_ms"].as_u64().is_some() + && fields["scopes"].as_array().is_some_and(|scopes| + scopes.iter().all(|scope| scope.as_str().is_some_and(|scope| SCOPES.contains(&scope)))) +} +fn base_valid(claim: &ClaimRecord) -> bool { + identity(claim) && digest_only(&claim.body["fields"]) + && digest(&claim.body["fields"]["credential_hash"]) +} +/// Shared validation for admission projection and consumers. The reference oracle +/// deliberately does not call this function. +pub fn structurally_valid(grant: &ClaimRecord, policy: &ClaimRecord) -> bool { + base_valid(grant) && policy_fields(policy) && grant.subject == policy.subject + && grant.origin == policy.origin && grant.actor == policy.actor + && principal(&grant.body["fields"]) == principal(&policy.body["fields"]) + && ["grant_id", "session_actor", "issuer", "profile"].iter() + .all(|key| grant.body["fields"][*key] == policy.body["fields"][*key]) +} +pub fn transition_valid(grant: &ClaimRecord, transition: &ClaimRecord) -> bool { + if transition.kind == POLICY { return structurally_valid(grant, transition); } + transition.kind == REVOKED && base_valid(grant) && identity(transition) + && transition.origin == grant.origin && transition.actor == grant.actor + && transition.subject == grant.subject + && transition.body["fields"]["grant_id"] == grant.body["fields"]["grant_id"] + && transition.body["fields"]["issuer"] == grant.body["fields"]["issuer"] + && principal(&transition.body["fields"]) == principal(&grant.body["fields"]) + && profile(&transition.body["fields"]) == profile(&grant.body["fields"]) +} + +pub fn expiry_key(value: u64) -> String { format!("{value:020}") } + +pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { + connection.execute_batch( + /* sqlite-large-value: allow-for-now lv-hd3babb5b6b9a owner=smallclaims::store::assistant_grant_authority TODO=chunk-or-reference-variable-columns */ + "CREATE TABLE IF NOT EXISTS assistant_grant_authority ( + claim_id TEXT NOT NULL, base_claim_id TEXT NOT NULL, + grant_subject TEXT NOT NULL, kind TEXT NOT NULL, origin TEXT NOT NULL, + actor TEXT NOT NULL, principal TEXT NOT NULL, profile TEXT NOT NULL, + expires_at TEXT NOT NULL, store_index INTEGER NOT NULL, + credential_hash TEXT, record TEXT NOT NULL, + PRIMARY KEY(claim_id,base_claim_id)); + CREATE INDEX IF NOT EXISTS assistant_grant_authority_transition_index + ON assistant_grant_authority(grant_subject,kind,origin,actor,base_claim_id,store_index DESC); + CREATE INDEX IF NOT EXISTS assistant_grant_authority_latest_index + ON assistant_grant_authority(grant_subject,kind,store_index DESC); + CREATE INDEX IF NOT EXISTS assistant_grant_authority_credential_index + ON assistant_grant_authority(credential_hash,store_index DESC) WHERE kind='custom.client.assistant.v1.granted'; + CREATE TABLE IF NOT EXISTS assistant_grant_effective ( + claim_id TEXT PRIMARY KEY, grant_subject TEXT NOT NULL, principal TEXT NOT NULL, + owner TEXT NOT NULL, profile TEXT NOT NULL, expires_at TEXT NOT NULL, + revoked INTEGER NOT NULL, grant_record TEXT NOT NULL); + CREATE INDEX IF NOT EXISTS assistant_grant_effective_active_index + ON assistant_grant_effective(principal,owner,revoked,expires_at,profile); + CREATE INDEX IF NOT EXISTS assistant_grant_effective_subject_index + ON assistant_grant_effective(grant_subject); + CREATE TABLE IF NOT EXISTS assistant_grant_pending ( + claim_id TEXT PRIMARY KEY, grant_subject TEXT NOT NULL, kind TEXT NOT NULL, + origin TEXT NOT NULL, actor TEXT NOT NULL, sequence INTEGER NOT NULL, + authenticated INTEGER NOT NULL, record TEXT NOT NULL); + CREATE INDEX IF NOT EXISTS assistant_grant_pending_subject_index + ON assistant_grant_pending(grant_subject,authenticated,origin,actor,kind); + CREATE INDEX IF NOT EXISTS assistant_grant_pending_writer_index + ON assistant_grant_pending(origin,authenticated,sequence,claim_id); + CREATE TABLE IF NOT EXISTS assistant_grant_dirty (claim_id TEXT PRIMARY KEY); + CREATE TABLE IF NOT EXISTS assistant_grant_auth_cursor ( + claim_id TEXT PRIMARY KEY, position INTEGER NOT NULL, record_rowid INTEGER NOT NULL, member_key TEXT NOT NULL); + CREATE TABLE IF NOT EXISTS assistant_grant_membership_dirty ( + writer TEXT PRIMARY KEY, sequence INTEGER NOT NULL, claim_id TEXT NOT NULL); + CREATE TABLE IF NOT EXISTS assistant_grant_membership_state ( + id INTEGER PRIMARY KEY CHECK(id=1), applied_generation INTEGER NOT NULL); + INSERT OR IGNORE INTO assistant_grant_membership_state VALUES(1,-1); + CREATE TABLE IF NOT EXISTS assistant_grant_local_appends (claim_id TEXT PRIMARY KEY); + CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_insert AFTER INSERT ON claims + WHEN NEW.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') + BEGIN INSERT OR IGNORE INTO assistant_grant_dirty VALUES(NEW.id); END; + DROP TRIGGER IF EXISTS assistant_grant_dirty_signature_insert; + DROP TRIGGER IF EXISTS assistant_grant_dirty_signature_insert_v2; + CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_signature_insert_v3 + AFTER INSERT ON replica_envelope_signatures + WHEN EXISTS(SELECT 1 FROM assistant_grant_membership_windows + WHERE writer=NEW.writer AND member_key=NEW.member_key + AND NEW.sequence>=start AND (end IS NULL OR NEW.sequence<=end)) + BEGIN + INSERT OR IGNORE INTO assistant_grant_dirty(claim_id) + SELECT records.claim_id FROM replica_records AS records + JOIN claims ON claims.id=records.claim_id + WHERE records.writer=NEW.writer AND records.sequence=NEW.sequence + AND records.envelope_hash=NEW.envelope_hash + AND claims.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked'); + DELETE FROM assistant_grant_auth_cursor WHERE claim_id IN ( + SELECT claim_id FROM replica_records + WHERE writer=NEW.writer AND sequence=NEW.sequence AND envelope_hash=NEW.envelope_hash); + END; + CREATE TABLE IF NOT EXISTS assistant_grant_membership_windows ( + writer TEXT NOT NULL, member_key TEXT NOT NULL, start INTEGER NOT NULL, end INTEGER, + PRIMARY KEY(writer,member_key));" + )?; + connection.execute(/* sqlite-large-value: allow-for-now lv-h3f117dab1bdd owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_local_origin',?1)", [local_origin])?; + Ok(()) +} + + +pub fn ready(connection: &Connection) -> Result<(), FractalError> { + let complete: bool = connection.query_row( + "SELECT COALESCE((SELECT value FROM meta WHERE key='assistant_grant_authority_version'),'')=?1", + [VERSION], |row| row.get(0), + ).map_err(internal)?; + if !complete { + return Err(FractalError::new("assistant-grant-authority-not-ready", "external-grant authority backfill is in progress; retry after it completes")); + } + Ok(()) +} +/// Durable maintenance work is independent of initial-backfill readiness. +pub fn maintenance_pending(connection: &Connection) -> Result { + let pending: bool = connection.query_row( + "SELECT COALESCE((SELECT value FROM meta WHERE key='assistant_grant_authority_version'),'')<>?1 + OR EXISTS(SELECT 1 FROM assistant_grant_dirty) + OR EXISTS(SELECT 1 FROM assistant_grant_membership_dirty)", + [VERSION], |row| row.get(0), + ).map_err(internal)?; + Ok(pending) +} +fn subject_pending(connection: &Connection, subject: &str) -> Result { + connection.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_dirty AS dirty + JOIN claims ON claims.id=dirty.claim_id WHERE claims.subject=?1) + OR EXISTS(SELECT 1 FROM assistant_grant_auth_cursor AS cursor + JOIN claims ON claims.id=cursor.claim_id WHERE claims.subject=?1) + OR EXISTS(SELECT 1 FROM assistant_grant_pending + WHERE grant_subject=?1 AND authenticated=0)", + [subject], |row| row.get(0), + ).map_err(internal) +} +/// A pending proof or unauthenticated revoke fences only its grant subject. +pub fn subject_ready(connection: &Connection, subject: &str) -> Result<(), FractalError> { + ready(connection)?; + if subject_pending(connection, subject)? { + return Err(FractalError::new("assistant-grant-subject-not-ready", "external-grant subject authentication is in progress")); + } + Ok(()) +} +fn decode(record: String) -> Result { + serde_json::from_str(&record).map_err(internal) +} +pub const TRANSITION_QUERY: &str = "SELECT record FROM assistant_grant_authority + WHERE grant_subject=?1 AND kind=?2 AND origin=?3 AND actor=?4 AND base_claim_id=?5 + ORDER BY store_index DESC LIMIT 1"; +pub fn transition(connection: &Connection, granted: &ClaimRecord, kind: &str) -> Result, FractalError> { + subject_ready(connection, &granted.subject)?; + transition_unchecked(connection, granted, kind).map_err(internal) +} +fn transition_unchecked(connection: &Connection, granted: &ClaimRecord, kind: &str) -> Result> { + let record: Option = connection.query_row(/* sqlite-large-value: allow-for-now lv-h80fb9d4725e0 owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ TRANSITION_QUERY, + params![granted.subject, kind, granted.origin, granted.actor, granted.id], |row| row.get(0)).optional()?; + record.map(|record| serde_json::from_str(&record).map_err(Into::into)).transpose() +} +pub fn latest(connection: &Connection, subject: &str, kind: &str) -> Result, FractalError> { + subject_ready(connection, subject)?; + let record: Option = connection.query_row( + "SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 AND kind=?2 ORDER BY store_index DESC LIMIT 1", + params![subject,kind], |row| row.get(0)).optional().map_err(internal)?; + record.map(decode).transpose() +} +pub const CANDIDATES_QUERY: &str = "SELECT grant_record FROM assistant_grant_effective + WHERE ?3 IS NOT NULL AND principal=?1 AND owner=?2 AND revoked=0 AND expires_at>?3 + AND (?4 IS NULL OR claim_id<>?4) AND (?5 IS NULL OR profile<>?5) + UNION ALL + SELECT grant_record FROM assistant_grant_effective + WHERE ?3 IS NULL AND principal=?1 AND owner=?2 + AND (?4 IS NULL OR claim_id<>?4) AND (?5 IS NULL OR profile<>?5)"; +/// Authenticated effective snapshots for conflict admission, not bearer access. +/// A pending revoke must not erase an opposite-profile conflict witness before +/// it authenticates. Bearer and transition readers independently fence subjects. +pub fn candidates(connection: &Connection, principal: &str, owner: &str, expiry_cut: Option, excluded: Option<&str>, ignored_profile: Option<&str>) -> Result, FractalError> { + ready(connection)?; + let mut statement = connection.prepare_cached(/* sqlite-large-value: allow-for-now lv-h556bdadaf8cd owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ CANDIDATES_QUERY).map_err(internal)?; + let records = statement.query_map(params![principal,owner,expiry_cut.map(expiry_key),excluded,ignored_profile], |row| row.get::<_,String>(0)) + .map_err(internal)?; + records.map(|record| decode(record.map_err(internal)?)).collect() +} +pub fn by_credential(connection: &Connection, digest: &str) -> Result, FractalError> { + ready(connection)?; + let record: Option = connection.query_row( + "SELECT record FROM assistant_grant_authority WHERE credential_hash=?1 AND kind='custom.client.assistant.v1.granted' ORDER BY store_index DESC LIMIT 1", + [digest], |row| row.get(0)).optional().map_err(internal)?; + let grant = record.map(decode).transpose()?; + match grant { + Some(grant) if !subject_pending(connection, &grant.subject)? => Ok(Some(grant)), + _ => Ok(None), + } +} +pub fn contains(connection: &Connection, claim_id: &str) -> Result { + ready(connection)?; + let subject: Option = connection.query_row( + "SELECT grant_subject FROM assistant_grant_authority WHERE claim_id=?1 LIMIT 1", + [claim_id], |row| row.get(0), + ).optional().map_err(internal)?; + match subject { + Some(subject) => Ok(!subject_pending(connection, &subject)?), + None => Ok(false), + } +} + +fn insert_authority(connection: &Connection, claim: &ClaimRecord, base: &ClaimRecord) -> Result { + let fields = &claim.body["fields"]; + Ok(connection.execute( + /* sqlite-large-value: allow-for-now lv-h60572e3ac6a5 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ + "INSERT OR IGNORE INTO assistant_grant_authority + (claim_id,base_claim_id,grant_subject,kind,origin,actor,principal,profile,expires_at,store_index,credential_hash,record) + VALUES(?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12)", + params![claim.id,base.id,claim.subject,claim.kind,claim.origin,claim.actor,principal(fields),profile(fields), + expiry_key(fields["expires_at_unix_ms"].as_u64().unwrap_or(0)),claim.store_index, + if claim.kind==GRANTED { fields["credential_hash"].as_str() } else { None },serde_json::to_string(claim)?], + )? != 0) +} +/// The only writer of effective rows. Rebuilding a subject uses authenticated +/// authority alone, including an earlier-arriving revoke, in the same transaction. +pub fn rebuild_subject(connection: &Connection, subject: &str) -> Result<()> { + connection.execute(/* sqlite-large-value: allow-for-now lv-h47619972ac92 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_effective WHERE grant_subject=?1", [subject])?; + let mut statement = connection.prepare_cached("SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 AND kind=?2")?; + let records = statement.query_map(params![subject,GRANTED], |row| row.get::<_,String>(0))?; + for record in records { + let record = record?; + let grant: ClaimRecord = serde_json::from_str(&record)?; + let policy_claim = transition_unchecked(connection,&grant,POLICY)?; + let policy = policy_claim.as_ref().unwrap_or(&grant); + if !structurally_valid(&grant,policy) { continue; } + let fields = &policy.body["fields"]; + connection.execute(/* sqlite-large-value: allow-for-now lv-h2909dd1a0b9c owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_effective(claim_id,grant_subject,principal,owner,profile,expires_at,revoked,grant_record) + VALUES(?1,?2,?3,?4,?5,?6,?7,?8)", + params![grant.id,grant.subject,principal(fields),grant.actor,profile(fields), + expiry_key(fields["expires_at_unix_ms"].as_u64().unwrap_or(0)), + transition_unchecked(connection,&grant,REVOKED)?.is_some(),record])?; + } + Ok(()) +} +fn attach_claim(connection: &Connection, claim: &ClaimRecord) -> Result<()> { + let mut changed = false; + if claim.kind == GRANTED { + // A malformed base stays pending until a valid issuer policy repairs it. + // Otherwise a newer malformed copy could mask a valid bearer lookup. + if structurally_valid(claim,claim) { + changed |= insert_authority(connection,claim,claim)?; + } + // Only this base's issuer prefix can attach to it. In particular, an + // authenticated wrong-actor history cannot enlarge later admission work. + let mut statement = connection.prepare_cached( + "SELECT record FROM assistant_grant_pending WHERE grant_subject=?1 + AND authenticated=1 AND origin=?2 AND actor=?3 AND kind<>?4")?; + let records = statement.query_map(params![claim.subject,claim.origin,claim.actor,GRANTED], |row| row.get::<_,String>(0))?; + for record in records { + let transition: ClaimRecord = serde_json::from_str(&record?)?; + if transition_valid(claim,&transition) { + if transition.kind == POLICY { + changed |= insert_authority(connection,claim,claim)?; + } + changed |= insert_authority(connection,&transition,claim)?; + } + } + } else { + let mut statement = connection.prepare_cached( + "SELECT record FROM assistant_grant_pending WHERE grant_subject=?1 + AND authenticated=1 AND kind=?2 AND origin=?3 AND actor=?4")?; + let records = statement.query_map(params![claim.subject,GRANTED,claim.origin,claim.actor], |row| row.get::<_,String>(0))?; + for record in records { + let grant: ClaimRecord = serde_json::from_str(&record?)?; + if transition_valid(&grant,claim) { + if claim.kind == POLICY { + changed |= insert_authority(connection,&grant,&grant)?; + } + changed |= insert_authority(connection,claim,&grant)?; + } + } + } + if changed { rebuild_subject(connection,&claim.subject)?; } + Ok(()) +} +fn local_origin(connection: &Connection) -> Result { + Ok(connection.query_row("SELECT value FROM meta WHERE key='assistant_grant_authority_local_origin'", [], |row| row.get(0))?) +} +/// Admission pays structural/authentication cost once. Invalid rows never enter +/// the authority or the pending-authentication writer/window index. +pub fn refresh_claim(connection: &Connection, id: &str) -> Result<()> { + // Receipt/local append boundary: only durable local admission is immediate. + // Remote first-authentication runs in maintenance after generation validation. + refresh_claim_inner(connection, id, false) +} + +fn refresh_claim_inner(connection: &Connection, id: &str, membership_current: bool) -> Result<()> { + static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| + format!("SELECT {CLAIM_COLUMNS} FROM claims WHERE id=?1")); + let claim = connection.prepare_cached(/* sqlite-large-value: allow-for-now lv-h1665a4a8cfdf owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ &QUERY)?.query_row(/* sqlite-large-value: allow-for-now lv-h5520ddeb5d20 owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ [id], claim_from_row).optional()?; + let Some(claim) = claim else { return Ok(()); }; + if !KINDS.contains(&claim.kind.as_str()) { return Ok(()); } + let valid = if claim.kind==GRANTED { base_valid(&claim) } + else if claim.kind==POLICY { policy_fields(&claim) } else { identity(&claim) }; + if valid { + let sequence: u64 = connection.query_row("SELECT replica_sequence FROM batches WHERE id=?1", [&claim.batch_id], |row| row.get(0))?; + // Only the local append transaction can create this durable admission + // fact. Origin text and the absence of a receipt prove nothing: legacy + // imports can also have neither envelopes nor replica records. + let local_append: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_local_appends WHERE claim_id=?1)", + [&claim.id], |row| row.get(0), + )?; + let admitted: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_pending WHERE claim_id=?1 AND authenticated=1)", + [&claim.id], |row| row.get(0), + )?; + let authentication = if admitted || (local_append && claim.origin == local_origin(connection)?) { + Some(true) + } else if membership_current { + authenticated_claim(connection,&claim.id)? + } else { + None + }; + let authenticated = authentication == Some(true); + let changed = connection.execute(/* sqlite-large-value: allow-for-now lv-h9cf86ad98d1e owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_pending(claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) + VALUES(?1,?2,?3,?4,?5,?6,?7,?8) ON CONFLICT(claim_id) DO UPDATE SET authenticated=excluded.authenticated + WHERE assistant_grant_pending.authenticated