@xtrape/capsule-contracts-node 0.1.0-public-review.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,179 @@
1
+ // src/index.ts
2
+ import { customAlphabet } from "nanoid";
3
+ import { z } from "zod";
4
+ var AgentStatus = ["PENDING", "ONLINE", "OFFLINE", "DISABLED", "REVOKED"];
5
+ var CapsuleServiceStatus = ["UNKNOWN", "HEALTHY", "UNHEALTHY", "STALE", "OFFLINE"];
6
+ var HealthStatus = ["UP", "DEGRADED", "DOWN", "UNKNOWN"];
7
+ var CommandStatus = ["PENDING", "RUNNING", "SUCCEEDED", "FAILED", "EXPIRED", "CANCELLED"];
8
+ var DangerLevel = ["LOW", "MEDIUM", "HIGH"];
9
+ var AuditActorType = ["USER", "AGENT", "SYSTEM"];
10
+ var AuditResult = ["SUCCESS", "FAILURE"];
11
+ var TokenStatus = ["ACTIVE", "REVOKED", "EXPIRED", "USED"];
12
+ var ErrorCode = {
13
+ INTERNAL_ERROR: "INTERNAL_ERROR",
14
+ VALIDATION_FAILED: "VALIDATION_FAILED",
15
+ UNAUTHORIZED: "UNAUTHORIZED",
16
+ FORBIDDEN: "FORBIDDEN",
17
+ NOT_FOUND: "NOT_FOUND",
18
+ CONFLICT: "CONFLICT",
19
+ CSRF_INVALID: "CSRF_INVALID",
20
+ ACTION_REQUIRES_CONFIRMATION: "ACTION_REQUIRES_CONFIRMATION",
21
+ COMMAND_EXPIRED: "COMMAND_EXPIRED",
22
+ TOKEN_REVOKED: "TOKEN_REVOKED",
23
+ TOKEN_EXPIRED: "TOKEN_EXPIRED",
24
+ AGENT_REVOKED: "AGENT_REVOKED",
25
+ AGENT_DISABLED: "AGENT_DISABLED"
26
+ };
27
+ var idPrefixes = ["wks_", "usr_", "agt_", "tok_", "svc_", "hlr_", "cfg_", "act_", "cmd_", "crs_", "aud_"];
28
+ var NANO = customAlphabet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-", 21);
29
+ function newId(prefix) {
30
+ return `${prefix}${NANO()}`;
31
+ }
32
+ var AnyJson = z.record(z.any());
33
+ var AgentStatusSchema = z.enum(AgentStatus);
34
+ var CapsuleServiceStatusSchema = z.enum(CapsuleServiceStatus);
35
+ var HealthStatusSchema = z.enum(HealthStatus);
36
+ var CommandStatusSchema = z.enum(CommandStatus);
37
+ var DangerLevelSchema = z.enum(DangerLevel).default("LOW");
38
+ var UserSchema = z.object({ id: z.string().startsWith("usr_"), username: z.string(), displayName: z.string().nullable().optional(), createdAt: z.string(), updatedAt: z.string() });
39
+ var UserRole = z.enum(["owner", "operator", "viewer"]);
40
+ var createUserRequestSchema = z.object({ username: z.string().min(1), password: z.string().min(12), displayName: z.string().optional(), role: UserRole.default("viewer") });
41
+ var updateUserRequestSchema = z.object({ displayName: z.string().optional(), role: UserRole.optional(), status: z.enum(["ACTIVE", "DISABLED"]).optional() });
42
+ var resetUserPasswordRequestSchema = z.object({ password: z.string().min(12) });
43
+ var AdminLoginRequestSchema = z.object({ username: z.string().min(1), password: z.string().min(1) });
44
+ var adminLoginRequestSchema = AdminLoginRequestSchema;
45
+ var AdminSessionSchema = z.object({ user: UserSchema, csrfToken: z.string(), expiresAt: z.string() });
46
+ var AgentSchema = z.object({ id: z.string().startsWith("agt_"), code: z.string(), name: z.string().nullable().optional(), mode: z.enum(["embedded", "sidecar", "external"]), runtime: z.string().nullable().optional(), status: AgentStatusSchema, lastHeartbeatAt: z.string().nullable().optional(), createdAt: z.string(), updatedAt: z.string() });
47
+ var RegistrationTokenSchema = z.object({ id: z.string().startsWith("tok_"), name: z.string(), status: z.enum(TokenStatus), expiresAt: z.string().nullable().optional(), usedAt: z.string().nullable().optional(), createdAt: z.string() });
48
+ var CreateRegistrationTokenRequestSchema = z.object({ name: z.string().default("Default registration token").optional(), expiresInSeconds: z.number().int().min(60).optional() });
49
+ var createRegistrationTokenRequestSchema = CreateRegistrationTokenRequestSchema;
50
+ var CreateRegistrationTokenResponseSchema = RegistrationTokenSchema.extend({ rawToken: z.string().startsWith("opstage_reg_") });
51
+ var CapsuleManifestSchema = z.object({ kind: z.literal("CapsuleService"), schemaVersion: z.string().default("1.0").optional(), code: z.string().min(1), name: z.string().min(1), description: z.string().optional(), version: z.string().min(1), runtime: z.enum(["nodejs", "java", "python", "go", "other"]), agentMode: z.enum(["embedded", "sidecar", "external"]), capabilities: z.array(z.string()).optional(), labels: z.record(z.string()).optional() }).passthrough();
52
+ var HealthReportInputSchema = z.object({ status: HealthStatusSchema, message: z.string().optional(), details: AnyJson.optional() });
53
+ var healthReportInputSchema = HealthReportInputSchema;
54
+ var ConfigItemInputSchema = z.object({ key: z.string(), label: z.string().optional(), type: z.string(), source: z.string().optional(), editable: z.boolean().optional(), sensitive: z.boolean().optional(), valuePreview: z.string().optional(), defaultValue: z.string().optional(), secretRef: z.string().optional() });
55
+ var configItemInputSchema = ConfigItemInputSchema;
56
+ var ActionDefinitionInputSchema = z.object({ name: z.string(), label: z.string(), description: z.string().optional(), dangerLevel: z.enum(DangerLevel).default("LOW").optional(), requiresConfirmation: z.boolean().optional(), category: z.string().optional(), order: z.number().int().optional(), inputSchema: AnyJson.optional(), outputSchema: AnyJson.optional(), timeoutSeconds: z.number().int().positive().optional() });
57
+ var actionDefinitionInputSchema = ActionDefinitionInputSchema;
58
+ var ReportedServiceSchema = z.object({ code: z.string().min(1).max(80), name: z.string().min(1).max(200), description: z.string().max(2e3).optional(), version: z.string().max(80).optional(), runtime: z.string().optional(), manifest: AnyJson, health: HealthReportInputSchema.optional(), configs: z.array(ConfigItemInputSchema).optional(), actions: z.array(ActionDefinitionInputSchema).optional() });
59
+ var reportedServiceSchema = ReportedServiceSchema;
60
+ var ServiceReportRequestSchema = z.object({ services: z.array(ReportedServiceSchema).min(1) });
61
+ var serviceReportRequestSchema = ServiceReportRequestSchema;
62
+ var RegisterAgentRequestSchema = z.object({ registrationToken: z.string().startsWith("opstage_reg_"), agent: z.object({ code: z.string(), name: z.string().optional(), mode: z.literal("embedded"), runtime: z.string().optional() }), service: ReportedServiceSchema.optional() });
63
+ var registerAgentRequestSchema = RegisterAgentRequestSchema;
64
+ var RegisterAgentResponseSchema = z.object({ agentId: z.string().startsWith("agt_"), agentToken: z.string().startsWith("opstage_agent_"), heartbeatIntervalSeconds: z.number().int(), commandPollIntervalSeconds: z.number().int() });
65
+ var AgentHeartbeatResponseSchema = z.object({ heartbeatIntervalSeconds: z.number().int(), commandPollIntervalSeconds: z.number().int() });
66
+ var AgentHeartbeatRequestSchema = z.object({ serviceId: z.string().startsWith("svc_").optional(), health: HealthReportInputSchema.optional() });
67
+ var agentHeartbeatRequestSchema = AgentHeartbeatRequestSchema;
68
+ var CapsuleServiceSchema = z.object({ id: z.string().startsWith("svc_"), agentId: z.string().startsWith("agt_").optional(), code: z.string(), name: z.string(), description: z.string().nullable().optional(), version: z.string().nullable().optional(), runtime: z.string().nullable().optional(), status: CapsuleServiceStatusSchema, healthStatus: HealthStatusSchema.optional(), lastReportedAt: z.string().nullable().optional(), lastHealthAt: z.string().nullable().optional(), createdAt: z.string(), updatedAt: z.string() });
69
+ var HealthReportSchema = z.object({ id: z.string().startsWith("hlr_"), serviceId: z.string().startsWith("svc_"), agentId: z.string().startsWith("agt_").optional(), status: HealthStatusSchema, message: z.string().nullable().optional(), details: AnyJson.optional(), reportedAt: z.string() });
70
+ var ConfigItemSchema = z.object({ id: z.string().startsWith("cfg_"), serviceId: z.string().startsWith("svc_"), key: z.string(), label: z.string().nullable().optional(), type: z.string(), source: z.string().nullable().optional(), editable: z.boolean().default(false), sensitive: z.boolean(), valuePreview: z.string().nullable().optional(), defaultValue: z.string().nullable().optional(), secretRef: z.string().nullable().optional() });
71
+ var ActionDefinitionSchema = z.object({ id: z.string().startsWith("act_"), serviceId: z.string().startsWith("svc_"), name: z.string(), label: z.string(), description: z.string().nullable().optional(), dangerLevel: z.enum(DangerLevel), requiresConfirmation: z.boolean(), category: z.string().optional(), order: z.number().int().optional(), inputSchema: AnyJson.optional(), outputSchema: AnyJson.optional(), timeoutSeconds: z.number().int().optional() });
72
+ var CapsuleServiceDetailSchema = CapsuleServiceSchema.extend({ manifest: AnyJson.optional(), health: HealthReportSchema.nullable().optional(), configs: z.array(ConfigItemSchema).optional(), actions: z.array(ActionDefinitionSchema).optional() });
73
+ var CreateActionCommandRequestSchema = z.object({ payload: AnyJson.optional(), confirmation: z.boolean().optional() });
74
+ var createActionCommandRequestSchema = CreateActionCommandRequestSchema;
75
+ var CommandSchema = z.object({ id: z.string().startsWith("cmd_"), agentId: z.string().startsWith("agt_"), serviceId: z.string().startsWith("svc_"), type: z.enum(["ACTION_PREPARE", "ACTION_EXECUTE", "ACTION"]), actionName: z.string(), status: CommandStatusSchema, payload: AnyJson.optional(), createdByUserId: z.string().startsWith("usr_").nullable().optional(), createdAt: z.string(), startedAt: z.string().nullable().optional(), completedAt: z.string().nullable().optional(), expiresAt: z.string().nullable().optional() });
76
+ var ReportCommandResultRequestSchema = z.object({ success: z.boolean(), message: z.string().optional(), data: AnyJson.optional(), error: AnyJson.optional(), startedAt: z.string().optional(), finishedAt: z.string().optional() });
77
+ var reportCommandResultRequestSchema = ReportCommandResultRequestSchema;
78
+ var CommandResultSchema = z.object({ id: z.string().startsWith("crs_"), commandId: z.string().startsWith("cmd_"), success: z.boolean(), message: z.string().nullable().optional(), data: AnyJson.optional(), error: AnyJson.optional(), reportedAt: z.string() });
79
+ var CommandDetailSchema = CommandSchema.extend({ result: CommandResultSchema.nullable().optional() });
80
+ var AuditEventSchema = z.object({ id: z.string().startsWith("aud_"), actorType: z.enum(AuditActorType), actorId: z.string().nullable().optional(), action: z.string(), targetType: z.string().nullable().optional(), targetId: z.string().nullable().optional(), result: z.enum(AuditResult), message: z.string().nullable().optional(), metadata: AnyJson.optional(), createdAt: z.string() });
81
+ var DashboardSummarySchema = z.object({ agentCounts: z.record(z.number().int()), serviceCounts: z.record(z.number().int()), commandCounts: z.record(z.number().int()), recentCommands: z.array(CommandSchema).optional(), recentAuditEvents: z.array(AuditEventSchema).optional() });
82
+ var SystemHealthSchema = z.object({ status: z.enum(["UP", "DEGRADED", "DOWN"]), timestamp: z.string(), version: z.string(), edition: z.literal("ce"), database: z.object({ status: z.enum(["UP", "DEGRADED", "DOWN"]), kind: z.enum(["sqlite", "postgres", "mysql"]).optional(), latencyMs: z.number().int().optional() }), uptimeSeconds: z.number().int().optional() });
83
+ var SystemVersionSchema = z.object({ version: z.string(), edition: z.literal("ce"), commit: z.string().optional(), buildTime: z.string().optional() });
84
+ var ListQueryBase = z.object({ page: z.coerce.number().int().min(1).default(1), pageSize: z.coerce.number().int().min(1).max(100).default(20), sort: z.string().optional() });
85
+ var HttpError = class extends Error {
86
+ constructor(httpStatus, code, publicMessage, details) {
87
+ super(publicMessage);
88
+ this.httpStatus = httpStatus;
89
+ this.code = code;
90
+ this.publicMessage = publicMessage;
91
+ this.details = details;
92
+ }
93
+ httpStatus;
94
+ code;
95
+ publicMessage;
96
+ details;
97
+ };
98
+ function parseSort(value, allowed) {
99
+ if (!value) return [];
100
+ return value.split(",").filter(Boolean).map((raw) => {
101
+ const desc = raw.startsWith("-");
102
+ const field = desc ? raw.slice(1) : raw;
103
+ if (!allowed.includes(field)) throw new HttpError(422, "VALIDATION_FAILED", `Unknown sort field: ${field}`);
104
+ return { field, direction: desc ? "desc" : "asc" };
105
+ });
106
+ }
107
+ function paginate(items, page, pageSize, total) {
108
+ return { data: items, pagination: { page, pageSize, total } };
109
+ }
110
+ export {
111
+ ActionDefinitionInputSchema,
112
+ ActionDefinitionSchema,
113
+ AdminLoginRequestSchema,
114
+ AdminSessionSchema,
115
+ AgentHeartbeatRequestSchema,
116
+ AgentHeartbeatResponseSchema,
117
+ AgentSchema,
118
+ AgentStatus,
119
+ AgentStatusSchema,
120
+ AnyJson,
121
+ AuditActorType,
122
+ AuditEventSchema,
123
+ AuditResult,
124
+ CapsuleManifestSchema,
125
+ CapsuleServiceDetailSchema,
126
+ CapsuleServiceSchema,
127
+ CapsuleServiceStatus,
128
+ CapsuleServiceStatusSchema,
129
+ CommandDetailSchema,
130
+ CommandResultSchema,
131
+ CommandSchema,
132
+ CommandStatus,
133
+ CommandStatusSchema,
134
+ ConfigItemInputSchema,
135
+ ConfigItemSchema,
136
+ CreateActionCommandRequestSchema,
137
+ CreateRegistrationTokenRequestSchema,
138
+ CreateRegistrationTokenResponseSchema,
139
+ DangerLevel,
140
+ DangerLevelSchema,
141
+ DashboardSummarySchema,
142
+ ErrorCode,
143
+ HealthReportInputSchema,
144
+ HealthReportSchema,
145
+ HealthStatus,
146
+ HealthStatusSchema,
147
+ HttpError,
148
+ ListQueryBase,
149
+ RegisterAgentRequestSchema,
150
+ RegisterAgentResponseSchema,
151
+ RegistrationTokenSchema,
152
+ ReportCommandResultRequestSchema,
153
+ ReportedServiceSchema,
154
+ ServiceReportRequestSchema,
155
+ SystemHealthSchema,
156
+ SystemVersionSchema,
157
+ TokenStatus,
158
+ UserRole,
159
+ UserSchema,
160
+ actionDefinitionInputSchema,
161
+ adminLoginRequestSchema,
162
+ agentHeartbeatRequestSchema,
163
+ configItemInputSchema,
164
+ createActionCommandRequestSchema,
165
+ createRegistrationTokenRequestSchema,
166
+ createUserRequestSchema,
167
+ healthReportInputSchema,
168
+ idPrefixes,
169
+ newId,
170
+ paginate,
171
+ parseSort,
172
+ registerAgentRequestSchema,
173
+ reportCommandResultRequestSchema,
174
+ reportedServiceSchema,
175
+ resetUserPasswordRequestSchema,
176
+ serviceReportRequestSchema,
177
+ updateUserRequestSchema,
178
+ z
179
+ };
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@xtrape/capsule-contracts-node",
3
+ "version": "0.1.0-public-review.0",
4
+ "description": "TypeScript contracts and Zod schemas for Xtrape Capsule and Opstage wire protocols.",
5
+ "keywords": [
6
+ "xtrape",
7
+ "capsule",
8
+ "opstage",
9
+ "contracts",
10
+ "zod",
11
+ "agent-sdk"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/xtrape-com/xtrape-capsule-contracts-node.git"
16
+ },
17
+ "homepage": "https://github.com/xtrape-com/xtrape-capsule-contracts-node#readme",
18
+ "bugs": {
19
+ "url": "https://github.com/xtrape-com/xtrape-capsule-contracts-node/issues"
20
+ },
21
+ "type": "module",
22
+ "main": "./dist/index.cjs",
23
+ "module": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js",
29
+ "require": "./dist/index.cjs"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "spec",
35
+ "README.md",
36
+ "LICENSE",
37
+ "NOTICE"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsup src/index.ts --format esm,cjs --dts",
41
+ "prepack": "pnpm build",
42
+ "test": "vitest run",
43
+ "typecheck": "tsc --noEmit",
44
+ "lint": "tsc --noEmit"
45
+ },
46
+ "dependencies": {
47
+ "nanoid": "^5.0.9",
48
+ "zod": "^3.25.0"
49
+ },
50
+ "devDependencies": {
51
+ "tsup": "^8.3.5",
52
+ "typescript": "^5.6.3",
53
+ "vitest": "^2.1.9"
54
+ },
55
+ "engines": {
56
+ "node": ">=20"
57
+ },
58
+ "publishConfig": {
59
+ "registry": "https://registry.npmjs.org/",
60
+ "access": "public"
61
+ },
62
+ "license": "Apache-2.0"
63
+ }
package/spec/.source ADDED
@@ -0,0 +1 @@
1
+ xtrape-capsule-docs@local
@@ -0,0 +1,213 @@
1
+ {
2
+ "$schema": "./audit-actions.schema.json",
3
+ "version": "0.1.0",
4
+ "comment": "Single source of truth for AuditEvent.action values used in CE v0.1. Action names are lowercase, dot-separated, and stable. New action names require a contract update.",
5
+ "namingRules": [
6
+ "lowercase, dot-separated",
7
+ "format: <subject>.<verb>[.<qualifier>]",
8
+ "subject is the dominant resource (agent, service, command, token, session, system)",
9
+ "verb is the past-tense or imperative observation (created, requested, completed, failed, revoked, ...)",
10
+ "qualifier is optional and disambiguates similar actions"
11
+ ],
12
+ "actions": [
13
+ {
14
+ "name": "session.login.succeeded",
15
+ "actorType": "USER",
16
+ "targetType": "User",
17
+ "summary": "Admin user successfully logged in."
18
+ },
19
+ {
20
+ "name": "session.login.failed",
21
+ "actorType": "USER",
22
+ "targetType": "User",
23
+ "summary": "Login attempt failed."
24
+ },
25
+ {
26
+ "name": "session.logout",
27
+ "actorType": "USER",
28
+ "targetType": "User",
29
+ "summary": "Admin user logged out."
30
+ },
31
+ {
32
+ "name": "session.csrf.refreshed",
33
+ "actorType": "USER",
34
+ "targetType": "User",
35
+ "summary": "Admin requested a new CSRF token."
36
+ },
37
+ {
38
+ "name": "registration_token.created",
39
+ "actorType": "USER",
40
+ "targetType": "RegistrationToken",
41
+ "summary": "Admin created a registration token."
42
+ },
43
+ {
44
+ "name": "registration_token.revoked",
45
+ "actorType": "USER",
46
+ "targetType": "RegistrationToken",
47
+ "summary": "Admin revoked a registration token."
48
+ },
49
+ {
50
+ "name": "registration_token.consumed",
51
+ "actorType": "AGENT",
52
+ "targetType": "RegistrationToken",
53
+ "summary": "An Agent consumed the registration token during register."
54
+ },
55
+ {
56
+ "name": "agent.registered",
57
+ "actorType": "AGENT",
58
+ "targetType": "Agent",
59
+ "summary": "Agent completed registration and received an AgentToken."
60
+ },
61
+ {
62
+ "name": "agent.heartbeat.received",
63
+ "actorType": "AGENT",
64
+ "targetType": "Agent",
65
+ "summary": "Agent heartbeat received (sampled, not every heartbeat).",
66
+ "sampled": true
67
+ },
68
+ {
69
+ "name": "agent.disabled",
70
+ "actorType": "USER",
71
+ "targetType": "Agent",
72
+ "summary": "Admin disabled an Agent."
73
+ },
74
+ {
75
+ "name": "agent.enabled",
76
+ "actorType": "USER",
77
+ "targetType": "Agent",
78
+ "summary": "Admin re-enabled an Agent."
79
+ },
80
+ {
81
+ "name": "agent.revoked",
82
+ "actorType": "USER",
83
+ "targetType": "Agent",
84
+ "summary": "Admin revoked an Agent token; the Agent must re-register."
85
+ },
86
+ {
87
+ "name": "agent_token.issued",
88
+ "actorType": "SYSTEM",
89
+ "targetType": "AgentToken",
90
+ "summary": "Backend issued an AgentToken in response to a successful registration."
91
+ },
92
+ {
93
+ "name": "agent_token.rejected",
94
+ "actorType": "AGENT",
95
+ "targetType": "AgentToken",
96
+ "summary": "Backend rejected an AgentToken (revoked/expired/invalid)."
97
+ },
98
+ {
99
+ "name": "service.reported",
100
+ "actorType": "AGENT",
101
+ "targetType": "CapsuleService",
102
+ "summary": "Agent reported (or updated) a Capsule Service manifest."
103
+ },
104
+ {
105
+ "name": "service.retired",
106
+ "actorType": "AGENT",
107
+ "targetType": "CapsuleService",
108
+ "summary": "Agent reported the service as retired."
109
+ },
110
+ {
111
+ "name": "service.action.requested",
112
+ "actorType": "USER",
113
+ "targetType": "CapsuleService",
114
+ "summary": "Admin requested an action on a Capsule Service; backend created a Command."
115
+ },
116
+ {
117
+ "name": "command.created",
118
+ "actorType": "USER",
119
+ "targetType": "Command",
120
+ "summary": "Backend persisted a new Command (paired with service.action.requested)."
121
+ },
122
+ {
123
+ "name": "command.dispatched",
124
+ "actorType": "AGENT",
125
+ "targetType": "Command",
126
+ "summary": "Agent polled and received the Command."
127
+ },
128
+ {
129
+ "name": "command.started",
130
+ "actorType": "AGENT",
131
+ "targetType": "Command",
132
+ "summary": "Agent reported startedAt."
133
+ },
134
+ {
135
+ "name": "command.completed",
136
+ "actorType": "AGENT",
137
+ "targetType": "Command",
138
+ "summary": "Agent reported successful CommandResult."
139
+ },
140
+ {
141
+ "name": "command.failed",
142
+ "actorType": "AGENT",
143
+ "targetType": "Command",
144
+ "summary": "Agent reported failure CommandResult."
145
+ },
146
+ {
147
+ "name": "system.agent.offline",
148
+ "actorType": "SYSTEM",
149
+ "targetType": "Workspace",
150
+ "summary": "agent-offline-sweep transitioned an Agent to OFFLINE."
151
+ },
152
+ {
153
+ "name": "system.service.stale",
154
+ "actorType": "SYSTEM",
155
+ "targetType": "Workspace",
156
+ "summary": "service-stale-sweep transitioned a service to STALE."
157
+ },
158
+ {
159
+ "name": "system.command.expired",
160
+ "actorType": "SYSTEM",
161
+ "targetType": "Workspace",
162
+ "summary": "command-ttl-sweep transitioned a Command to EXPIRED."
163
+ },
164
+ {
165
+ "name": "system.bootstrap.completed",
166
+ "actorType": "SYSTEM",
167
+ "targetType": "Workspace",
168
+ "summary": "First-run bootstrap created the default workspace and admin."
169
+ },
170
+ {
171
+ "name": "user.created",
172
+ "actorType": "USER",
173
+ "targetType": "User",
174
+ "summary": "Admin created a new user."
175
+ },
176
+ {
177
+ "name": "user.updated",
178
+ "actorType": "USER",
179
+ "targetType": "User",
180
+ "summary": "Admin updated a user's role or status."
181
+ },
182
+ {
183
+ "name": "user.password.reset",
184
+ "actorType": "USER",
185
+ "targetType": "User",
186
+ "summary": "Admin reset a user's password."
187
+ },
188
+ {
189
+ "name": "command.cancelled",
190
+ "actorType": "USER",
191
+ "targetType": "Command",
192
+ "summary": "Admin cancelled a pending or running Command."
193
+ },
194
+ {
195
+ "name": "maintenance.triggered",
196
+ "actorType": "USER",
197
+ "targetType": "Workspace",
198
+ "summary": "Admin manually triggered a maintenance run."
199
+ },
200
+ {
201
+ "name": "maintenance.run",
202
+ "actorType": "SYSTEM",
203
+ "targetType": "Workspace",
204
+ "summary": "Scheduled maintenance run completed."
205
+ },
206
+ {
207
+ "name": "backup.sqlite.created",
208
+ "actorType": "USER",
209
+ "targetType": "Backup",
210
+ "summary": "Admin created a SQLite backup."
211
+ }
212
+ ]
213
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "./id-prefixes.schema.json",
3
+ "version": "0.1.0",
4
+ "comment": "Single source of truth for typed-ID prefixes used by newId(prefix). Each ID is `<prefix>_<base32-or-ulid>`. Prefixes are stable; renaming a prefix is a breaking change.",
5
+ "format": {
6
+ "shape": "<prefix>_<random>",
7
+ "randomScheme": "ulid (Crockford base32, 26 chars) — see 08-decisions/0001 for rationale",
8
+ "separator": "_",
9
+ "casing": "lowercase prefix; uppercase ULID body",
10
+ "example": "agt_01HZX5TQYP2N9VRJ8WTRQVZ8K2"
11
+ },
12
+ "prefixes": [
13
+ { "prefix": "wks", "type": "Workspace", "comment": "Default workspace ID; CE v0.1 ships exactly one." },
14
+ { "prefix": "usr", "type": "AdminUser", "comment": "Local admin user." },
15
+ { "prefix": "ses", "type": "Session", "comment": "Admin session record (server-side)." },
16
+ { "prefix": "agt", "type": "Agent", "comment": "Agent identity." },
17
+ { "prefix": "tok", "type": "RegistrationToken", "comment": "Registration token (the row; the raw token value is generated separately via newToken('reg'))." },
18
+ { "prefix": "atk", "type": "AgentToken", "comment": "Agent token (the row; raw token via newToken('agt'))." },
19
+ { "prefix": "svc", "type": "CapsuleService", "comment": "Capsule Service registered by an Agent." },
20
+ { "prefix": "act", "type": "ActionDefinition", "comment": "Action declared on a service manifest." },
21
+ { "prefix": "cmd", "type": "Command", "comment": "Command for an Agent to execute." },
22
+ { "prefix": "res", "type": "CommandResult", "comment": "Optional separate row for command results; CE v0.1 may inline into Command." },
23
+ { "prefix": "evt", "type": "AuditEvent", "comment": "Audit event row." },
24
+ { "prefix": "hlt", "type": "HealthReport", "comment": "Health report snapshot (latest persisted per service)." },
25
+ { "prefix": "cfg", "type": "ConfigItem", "comment": "Visible config item attached to a service manifest." },
26
+ { "prefix": "set", "type": "SystemSetting", "comment": "Bootstrap and runtime setting row." }
27
+ ],
28
+ "tokenPrefixes": [
29
+ { "tokenKind": "RegistrationToken.rawValue", "prefix": "opstage_reg", "comment": "Wire format for raw registration token; backend stores only the SHA-256 hash." },
30
+ { "tokenKind": "AgentToken.rawValue", "prefix": "opstage_agt", "comment": "Wire format for raw Agent token; backend stores only the SHA-256 hash." }
31
+ ]
32
+ }
@@ -0,0 +1,128 @@
1
+ {
2
+ "$schema": "./status-enums.schema.json",
3
+ "version": "0.1.0",
4
+ "comment": "Single source of truth for all status enumerations used in the CE v0.1 wire format. Each binding repo (xtrape-capsule-contracts-node, etc.) generates language-native enum types from this file.",
5
+ "enums": {
6
+ "AgentStatus": {
7
+ "description": "Lifecycle state of an Agent. PENDING = registered but no heartbeat yet; ONLINE = heartbeating; OFFLINE = missed offline threshold; DISABLED = paused by admin; REVOKED = token revoked.",
8
+ "values": [
9
+ { "value": "PENDING", "meaning": "Agent registered but has not yet reported a heartbeat." },
10
+ { "value": "ONLINE", "meaning": "Agent has reported a heartbeat within OPSTAGE_AGENT_OFFLINE_THRESHOLD_SECONDS." },
11
+ { "value": "OFFLINE", "meaning": "Agent has not reported within the offline threshold; sweepers transitioned PENDING/ONLINE → OFFLINE." },
12
+ { "value": "DISABLED", "meaning": "Admin paused the Agent; the Agent token is rejected with AGENT_DISABLED." },
13
+ { "value": "REVOKED", "meaning": "Admin revoked the Agent token; the Agent must re-register; token is rejected with AGENT_REVOKED." }
14
+ ],
15
+ "transitions": [
16
+ { "from": "PENDING", "to": ["ONLINE", "OFFLINE", "DISABLED", "REVOKED"] },
17
+ { "from": "ONLINE", "to": ["OFFLINE", "DISABLED", "REVOKED"] },
18
+ { "from": "OFFLINE", "to": ["ONLINE", "DISABLED", "REVOKED"] },
19
+ { "from": "DISABLED", "to": ["ONLINE", "REVOKED"] },
20
+ { "from": "REVOKED", "to": [] }
21
+ ]
22
+ },
23
+ "CapsuleServiceStatus": {
24
+ "description": "Effective lifecycle state of a Capsule Service. Persisted by the backend as derived from agent.status, lastReportedAt, and admin actions.",
25
+ "values": [
26
+ { "value": "PENDING", "meaning": "Service was reported by an Agent but has not yet sent a health report." },
27
+ { "value": "UP", "meaning": "Service has reported a healthy status within freshness threshold." },
28
+ { "value": "DEGRADED", "meaning": "Service reports healthStatus=DEGRADED OR last health is stale but Agent online." },
29
+ { "value": "DOWN", "meaning": "Service reports healthStatus=DOWN." },
30
+ { "value": "STALE", "meaning": "Last service report is older than OPSTAGE_HEALTH_STALE_THRESHOLD_SECONDS." },
31
+ { "value": "OFFLINE", "meaning": "Owning Agent is OFFLINE/DISABLED/REVOKED — derived effective state." },
32
+ { "value": "RETIRED", "meaning": "Service was explicitly retired by Agent (no longer reported)." }
33
+ ],
34
+ "derivationOrder": [
35
+ "If agent.status in (DISABLED, REVOKED) → OFFLINE",
36
+ "If agent.status == OFFLINE → OFFLINE",
37
+ "If service was retired → RETIRED",
38
+ "If lastReportedAt older than healthStaleThreshold → STALE",
39
+ "Else use last reported HealthStatus mapping (UP/DEGRADED/DOWN)"
40
+ ]
41
+ },
42
+ "HealthStatus": {
43
+ "description": "Status reported by a service via Agent health endpoint. Distinct from CapsuleServiceStatus (which is the effective derived state).",
44
+ "values": [
45
+ { "value": "UP", "meaning": "Service is healthy." },
46
+ { "value": "DEGRADED", "meaning": "Service is reachable but reports a degraded condition (e.g., slow dependency)." },
47
+ { "value": "DOWN", "meaning": "Service self-reports unhealthy." },
48
+ { "value": "UNKNOWN", "meaning": "Service has no health probe yet (initial state)." }
49
+ ]
50
+ },
51
+ "CommandStatus": {
52
+ "description": "Lifecycle state of a Command. Strict transitions enforced by backend.",
53
+ "values": [
54
+ { "value": "PENDING", "meaning": "Command created; not yet polled by Agent." },
55
+ { "value": "DISPATCHED","meaning": "Command was returned to the Agent in a poll response." },
56
+ { "value": "RUNNING", "meaning": "Agent reported startedAt." },
57
+ { "value": "SUCCEEDED", "meaning": "Terminal: Agent reported successful CommandResult." },
58
+ { "value": "FAILED", "meaning": "Terminal: Agent reported failure CommandResult." },
59
+ { "value": "EXPIRED", "meaning": "Terminal: Command past expiresAt before completion." },
60
+ { "value": "CANCELED", "meaning": "Terminal: admin canceled the Command (reserved for EE; CE v0.1 may not expose UI but enum is reserved)." }
61
+ ],
62
+ "terminal": ["SUCCEEDED", "FAILED", "EXPIRED", "CANCELED"],
63
+ "transitions": [
64
+ { "from": "PENDING", "to": ["DISPATCHED", "EXPIRED", "CANCELED"] },
65
+ { "from": "DISPATCHED", "to": ["RUNNING", "EXPIRED", "CANCELED"] },
66
+ { "from": "RUNNING", "to": ["SUCCEEDED", "FAILED", "EXPIRED", "CANCELED"] },
67
+ { "from": "SUCCEEDED", "to": [] },
68
+ { "from": "FAILED", "to": [] },
69
+ { "from": "EXPIRED", "to": [] },
70
+ { "from": "CANCELED", "to": [] }
71
+ ]
72
+ },
73
+ "TokenStatus": {
74
+ "description": "Lifecycle state of a RegistrationToken or AgentToken.",
75
+ "values": [
76
+ { "value": "ACTIVE", "meaning": "Token is valid and usable." },
77
+ { "value": "USED", "meaning": "Registration token has been consumed (one-shot)." },
78
+ { "value": "REVOKED", "meaning": "Admin revoked the token." },
79
+ { "value": "EXPIRED", "meaning": "Token past expiresAt." }
80
+ ]
81
+ },
82
+ "AuditResult": {
83
+ "description": "Result of an audited operation.",
84
+ "values": [
85
+ { "value": "SUCCESS", "meaning": "Operation succeeded." },
86
+ { "value": "FAILURE", "meaning": "Operation failed; metadata.errorCode SHOULD be populated." },
87
+ { "value": "DENIED", "meaning": "Operation was rejected by authorization policy." }
88
+ ]
89
+ },
90
+ "ActorType": {
91
+ "description": "Type of actor that initiated an audited operation.",
92
+ "values": [
93
+ { "value": "USER", "meaning": "An admin user (browser session)." },
94
+ { "value": "AGENT", "meaning": "An Agent (bearer token)." },
95
+ { "value": "SYSTEM", "meaning": "A background process (sweeper, bootstrap)." }
96
+ ]
97
+ },
98
+ "TargetType": {
99
+ "description": "Type of resource targeted by an audited operation.",
100
+ "values": [
101
+ { "value": "AGENT" },
102
+ { "value": "CAPSULE_SERVICE" },
103
+ { "value": "COMMAND" },
104
+ { "value": "REGISTRATION_TOKEN" },
105
+ { "value": "AGENT_TOKEN" },
106
+ { "value": "ADMIN_USER" },
107
+ { "value": "WORKSPACE" },
108
+ { "value": "SYSTEM_SETTING" }
109
+ ]
110
+ },
111
+ "DangerLevel": {
112
+ "description": "Self-declared danger level of an ActionDefinition. UI uses this to choose confirmation UX.",
113
+ "values": [
114
+ { "value": "LOW", "meaning": "Idempotent and safe (e.g. echo, runHealthCheck)." },
115
+ { "value": "MEDIUM", "meaning": "May change service state but reversible." },
116
+ { "value": "HIGH", "meaning": "Destructive or hard to reverse; UI MUST require explicit confirmation." }
117
+ ]
118
+ },
119
+ "AgentMode": {
120
+ "description": "Deployment mode of an Agent.",
121
+ "values": [
122
+ { "value": "embedded", "meaning": "Agent runs in-process inside a Capsule Service (CE v0.1 baseline)." },
123
+ { "value": "sidecar", "meaning": "Agent runs as a separate process beside services. Reserved for EE.", "reservedFor": "EE" },
124
+ { "value": "external", "meaning": "Agent runs as a separate fleet manager. Reserved for EE/Cloud.", "reservedFor": "EE" }
125
+ ]
126
+ }
127
+ }
128
+ }