@xtrape/capsule-contracts-node
v0.4.0
Published
TypeScript contracts and Zod schemas for Xtrape Capsule and Opstage wire protocols.
Maintainers
Readme
@xtrape/capsule-contracts-node
TypeScript contracts and Zod schemas for Xtrape Capsule and Opstage wire protocols.
@xtrape/capsule-contracts-node is the shared TypeScript contract package for
Opstage CE, Agent SDKs, and Capsule Service integrations. It exports Zod
schemas, inferred TypeScript types, enum values, ID helpers, pagination helpers,
and protocol error helpers for the Agent/Admin/System wire contracts.
Package status: Xtrape Capsule is currently in Public Review before the
v0.1.0 Public Previewrelease. This package is published to npm under thepublic-reviewdist-tag. APIs, contracts, deployment instructions, and SDK interfaces may still change.
Install
During Public Review, install the prerelease package with:
pnpm add @xtrape/capsule-contracts-node@public-reviewThe current Public Review version may change before v0.1.0.
For this repository itself:
pnpm install
pnpm buildWhat is Included
The package currently exports:
- Zod itself as
zfor consumers that want one compatible Zod instance. - Status enum arrays and types:
AgentStatus,CapsuleServiceStatus,HealthStatus,CommandStatus,DangerLevel,AuditActorType,AuditResult,TokenStatus,AgentMode. - Admin schemas: users, sessions, registration token requests/responses.
- Agent schemas: registration, heartbeat, service report, command result.
- Capsule Service schemas: manifest, health, config, action, service detail.
- Command schemas: create command, command detail, command result.
- Audit and dashboard schemas.
- System health/version schemas.
- Helpers:
parseSort,paginate,HttpError,ListQueryBase.
Validate Agent Registration
import { RegisterAgentRequestSchema } from "@xtrape/capsule-contracts-node";
const request = RegisterAgentRequestSchema.parse(input);
// request.registrationToken starts with opstage_reg_
// request.agent.mode is embedded or ophubLowercase aliases are also exported for backend compatibility:
import { registerAgentRequestSchema } from "@xtrape/capsule-contracts-node";
const request = registerAgentRequestSchema.parse(input);v0.3 OpHub and Metadata
v0.3 adds the experimental ophub Agent mode. sidecar and base-image
remain OpHub deployment forms, but the wire contract should use
mode: "ophub" for an OpHub that represents one or more local Capsule
Services.
import { RegisterAgentRequestSchema, ServiceReportRequestSchema } from "@xtrape/capsule-contracts-node";
RegisterAgentRequestSchema.parse({
registrationToken: "opstage_reg_...",
agent: {
code: "ophub-a",
name: "OpHub A",
mode: "ophub",
runtime: "go",
},
});
ServiceReportRequestSchema.parse({
services: [
{
code: "svc-one",
name: "Service One",
version: "0.3.0",
runtime: "nodejs",
manifest: {
kind: "CapsuleService",
code: "svc-one",
name: "Service One",
version: "0.3.0",
runtime: "nodejs",
agentMode: "ophub",
capabilities: [{ name: "inventory.read", label: "Inventory read" }],
events: [{ name: "inventory.changed", direction: "publish", designOnly: true }],
},
},
],
});Capability metadata is implemented as declarative service metadata. Event
metadata is intentionally a foundation for future Capsule Bus work; designOnly
events must not be treated as a working event bus.
Validate Service Report
import { ServiceReportRequestSchema } from "@xtrape/capsule-contracts-node";
const report = ServiceReportRequestSchema.parse({
services: [
{
code: "hello-capsule",
name: "Hello Capsule",
version: "0.1.0",
runtime: "nodejs",
manifest: {
kind: "CapsuleService",
schemaVersion: "1.0",
code: "hello-capsule",
name: "Hello Capsule",
version: "0.1.0",
runtime: "nodejs",
agentMode: "embedded",
},
},
],
});Validate Health Report
import { HealthReportInputSchema } from "@xtrape/capsule-contracts-node";
const health = HealthReportInputSchema.parse({
status: "UP",
message: "ok",
details: { uptimeSeconds: 123 },
});Allowed health statuses are:
import { HealthStatus } from "@xtrape/capsule-contracts-node";
console.log(HealthStatus); // ["UP", "DEGRADED", "DOWN", "UNKNOWN"]HealthStatus is the protocol-level status reported by Agents and Capsule
Services:
UPDEGRADEDDOWNUNKNOWN
Opstage may derive an operator-facing effectiveStatus such as:
HEALTHYUNHEALTHYSTALEOFFLINE
Validate Config and Action Definitions
import {
ConfigItemInputSchema,
ActionDefinitionInputSchema,
} from "@xtrape/capsule-contracts-node";
const config = ConfigItemInputSchema.parse({
key: "UPSTREAM_BASE_URL",
type: "string",
sensitive: false,
valuePreview: "https://api.example.test",
});
const action = ActionDefinitionInputSchema.parse({
name: "reload-cache",
label: "Reload Cache",
dangerLevel: "MEDIUM",
requiresConfirmation: true,
});Validate Action Prepare Result
Use ActionPrepareResultSchema to validate the action-prepare payload directly:
import { ActionPrepareResultSchema } from "@xtrape/capsule-contracts-node";
const prepare = ActionPrepareResultSchema.parse({
initialPayload: { message: "hello" },
currentState: { service: "ready" },
inputSchema: {
type: "object",
properties: {
message: { type: "string", default: "hello" },
},
},
});When reported back to Opstage for an ACTION_PREPARE command, this shape is
placed under ReportCommandResultRequest.data. Command result reporting still
uses ReportCommandResultRequestSchema:
import { ReportCommandResultRequestSchema } from "@xtrape/capsule-contracts-node";
const prepareResult = ReportCommandResultRequestSchema.parse({
success: true,
data: {
action: { name: "echo", label: "Echo", dangerLevel: "LOW" },
inputSchema: {
type: "object",
properties: { message: { type: "string", default: "hello" } },
},
initialPayload: { message: "hello" },
currentState: { service: "ready" },
},
});Validate Command Result
import { ReportCommandResultRequestSchema } from "@xtrape/capsule-contracts-node";
const result = ReportCommandResultRequestSchema.parse({
success: true,
message: "Done",
data: { count: 1 },
startedAt: new Date().toISOString(),
finishedAt: new Date().toISOString(),
});Failed results should include an operator-safe message and structured error:
ReportCommandResultRequestSchema.parse({
success: false,
message: "Provider challenge page detected.",
error: {
code: "ACTION_FAILED",
retryable: false,
},
});Error Codes
The ErrorCode export contains protocol-level error code constants currently
used by CE and SDKs:
import { ErrorCode } from "@xtrape/capsule-contracts-node";
throw new Error(ErrorCode.VALIDATION_FAILED);Currently exported codes include:
INTERNAL_ERRORVALIDATION_FAILEDUNAUTHORIZEDFORBIDDENNOT_FOUNDCONFLICTCSRF_INVALIDACTION_REQUIRES_CONFIRMATIONCOMMAND_EXPIREDTOKEN_REVOKEDTOKEN_EXPIREDAGENT_REVOKEDAGENT_DISABLED
See the OpenAPI contract and docs site for endpoint-specific errors.
ID generation
This package validates IDs at the wire boundary (via Zod) but does not mint
them. Until v0.1.x there was a small newId() helper plus an idPrefixes
table; both were removed in 0.2.0 to keep the contracts surface focused on
the wire spec — see CHANGELOG.md and the
"Breaking changes" section at the top of this README.
Consumers that need local ID generation should provide their own factory.
Example using nanoid directly:
import { customAlphabet } from "nanoid";
const idBody = customAlphabet("0123456789abcdefghijklmnopqrstuvwxyz", 21);
const commandId = `cmd_${idBody()}`;Documented ID prefixes in use across CE and the Agent SDK include wks_,
usr_, agt_, tok_, svc_, hlr_, cfg_, act_, cmd_, crs_, and
aud_. These are enforced by the Zod schemas via z.string().startsWith(...).
List Helpers
import {
ListQueryBase,
parseSort,
paginate,
} from "@xtrape/capsule-contracts-node";
const query = ListQueryBase.parse({ page: "1", pageSize: "20" });
const sort = parseSort("-createdAt", ["createdAt", "name"]);
const response = paginate(items, query.page, query.pageSize, total);Used By
xtrape-capsule-ce— Opstage CE backend validation and protocol handling.xtrape-capsule-agent-node— Node embedded Agent SDK request/response types.xtrape-capsule-demo— End-to-end runnable Capsule Service that imports these schemas through the Agent SDK.- Capsule Service implementations that want local validation before reporting to Opstage.
Compatibility
| Package | Compatible with |
| -------------------------------------- | ---------------------------------------- |
| @xtrape/[email protected] | Opstage CE 0.2.x and Agent SDK 0.2.x |
| @xtrape/[email protected] | Opstage CE 0.1.x and Agent SDK 0.1.x |
Pin matching minor versions across CE, Agent SDK, and Contracts. The wire
protocol may still evolve before v1.0.
Breaking changes in 0.2.0
newId()removed. The helper minted random IDs with a prefix; it was never used by CE (entity IDs are minted in the backend). External consumers that importednewIdmust wire their own factory — see the ID generation section above.idPrefixesconstant andIdPrefixtype removed. Same rationale.nanoidruntime dependency removed as a consequence. Consumers that relied on a transitivenanoidinstall must now add it directly.
The wire schemas themselves are unchanged between 0.1.x and 0.2.x;
existing 0.1.x agents continue to validate against a 0.2.x backend.
Schema Stability
The package follows semver. For Public Review and Public Preview, the guarantees per schema group are:
| Group | Stability | Notes |
| ---------------------------------------------------------------------------------------------------------------- | :---------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Status enums (AgentStatus, CapsuleServiceStatus, HealthStatus, CommandStatus, DangerLevel, TokenStatus) | Stable | New values may be added in minor versions; existing values will not be removed before v1.0. |
| Agent ↔ Backend wire schemas (RegisterAgentRequest, AgentHeartbeat*, ServiceReport*, ReportCommandResult*) | Evolving | Field shape is stable; additive optional fields may land in minor versions. Required fields will not be added before v1.0 without a deprecation cycle. |
| Capsule Service shapes (CapsuleManifest, ReportedService, HealthReportInput, ConfigItemInput, ActionDefinitionInput) | Evolving | Same policy as wire schemas. |
| Persisted shapes (Agent, CapsuleService, ConfigItem, ActionDefinition, Command*, AuditEvent, User) | Evolving | Track CE storage; safe to consume read-only. |
| ActionPrepareResultSchema | Provisional | Added in 0.1.0-public-review.0. Field shape may still tighten before v1.0. |
| Command.type enum | Evolving | Currently ACTION_PREPARE / ACTION_EXECUTE. New types may be added. |
| Error codes (ErrorCode) | Evolving | New codes may be added. Existing codes will not change meaning before v1.0. |
| Helpers (parseSort, paginate, HttpError, ListQueryBase) | Provisional | Helpful for backend-style consumers but not strictly part of the wire spec; may move to a separate utility package in a future minor. (newId / idPrefixes / IdPrefix were removed in 0.2.0 — see "Breaking changes in 0.2.0" above.) |
Until v1.0, pin to a single minor across CE / Agent SDK / Contracts.
Breaking changes will be called out in CHANGELOG.md.
Documentation
- Contracts overview: https://xtrape-com.github.io/xtrape-capsule-site/contracts/overview
- Manifest contract: https://xtrape-com.github.io/xtrape-capsule-site/contracts/manifest
- Health contract: https://xtrape-com.github.io/xtrape-capsule-site/contracts/health
- Actions contract: https://xtrape-com.github.io/xtrape-capsule-site/contracts/actions
- Errors: https://xtrape-com.github.io/xtrape-capsule-site/contracts/errors
- Opstage CE: https://xtrape-com.github.io/xtrape-capsule-site/opstage-ce/overview
Contributing
See CONTRIBUTING.md for schema change workflow and PR checks. See SECURITY.md for vulnerability reporting and contract validation safety guidance.
License
Apache-2.0. "Xtrape", "Xtrape Capsule", and "Opstage" are trademarks of their respective owners; the open-source license does not grant trademark rights.
v0.4 Capsule Bus Experimental
v0.4 adds an experimental Capsule Bus contract surface for CE's built-in SQLite-backed in-process event-to-command router. It is intentionally small, single-node, and disabled by default; it is not a standalone Bus Server, external broker (NATS / RabbitMQ / Redis Streams / Kafka), workflow DSL, or service mesh. No fan-out (maxCommandsPerEvent) in v0.4 — one matched route produces at most one ACTION_EXECUTE command.
Key exports:
BusEventEnvelopeSchemaPublishBusEventRequestSchemaPublishBusEventResponseSchemaBusRouteRuleSchemaCreateBusRouteRuleRequestSchema
Minimal event payload:
BusEventEnvelopeSchema.parse({
eventType: "demo.item.created",
sourceServiceCode: "demo-worker",
payload: { itemId: "item-1" },
});All schemas include or default experimental: "v0.4-experimental"; consumers should treat the wire surface as unstable until v1.0.
