@cleocode/contracts 2026.9.26 → 2026.10.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nexus-cloud.d.ts","sourceRoot":"","sources":["../src/nexus-cloud.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,406 @@
1
+ /**
2
+ * Cleo Nexus remote reads: what `cleo cloud status|whoami|devices|projects`
3
+ * parse from the API and emit in their LAFS envelopes (cleo-nexus device
4
+ * contract v2.15, §4.1, §4.2 E2/E3/E5/E13/E14/E15, §4.4), plus the error
5
+ * mapping table of §4.0.4.
6
+ *
7
+ * The response schemas are the client's tolerant reading of §4.1: every field
8
+ * the CLI reports is named, unknown fields are stripped (never `.strict()`,
9
+ * §4 preamble), and fields the deployed server does not send on every route
10
+ * yet (E2's `device` is a subset of `DeviceView`, E13 has no
11
+ * `lastPresenceAt`) are optional. They are not part of `./cloud`, which
12
+ * mirrors the server's `@cleo-nexus/shared` package one-to-one.
13
+ *
14
+ * Nothing here carries a token, a key or a filesystem path the server sent;
15
+ * the local paths in {@link CloudStatusLocal} are locations only.
16
+ *
17
+ * This file is types + zod schemas + const data only (arch gate 10).
18
+ *
19
+ * @task T12871
20
+ * @epic T12323
21
+ */
22
+ import { z } from 'zod';
23
+ // ---------- shared pieces (§4.1) ----------
24
+ /** Device states (§4.1 `DeviceState`). */
25
+ export const NEXUS_DEVICE_STATES = ['active', 'signed-out', 'revoked'];
26
+ /** Device-credential profiles (§2.3, §4.1 `DeviceProfile`). */
27
+ export const NEXUS_CLOUD_PROFILES = ['device', 'read-only'];
28
+ /** The `state` filter of `GET /v1/devices` (E5, `ListDevicesQuery.state`). */
29
+ export const NEXUS_DEVICE_LIST_STATES = ['active', 'signed-out', 'revoked', 'all'];
30
+ /** Largest page the list endpoints accept (§4.0.3). */
31
+ export const NEXUS_PAGE_LIMIT_MAX = 200;
32
+ /** Default number of pages a `cleo cloud` list follows before it stops and says so. */
33
+ export const NEXUS_CLOUD_MAX_PAGES = 25;
34
+ /** Seconds within which a replica's presence counts as fresh (§4.1 `PRESENCE_FRESH_SECONDS`). */
35
+ export const NEXUS_PRESENCE_FRESH_SECONDS = 86_400;
36
+ /**
37
+ * The device state a newer server value parses as. Not `active`, so every
38
+ * active-only check fails closed instead of the whole command failing.
39
+ */
40
+ export const NEXUS_DEVICE_STATE_UNKNOWN = 'unknown';
41
+ const isoTime = z.iso.datetime({ offset: true });
42
+ /** A profile the CLI does not know reads as none, never as a parse failure. */
43
+ const profile = z.enum(NEXUS_CLOUD_PROFILES).nullable().catch(null);
44
+ /** A device state; a value added by a newer server reads as `unknown` (not active). */
45
+ const deviceState = z
46
+ .enum([...NEXUS_DEVICE_STATES, NEXUS_DEVICE_STATE_UNKNOWN])
47
+ .catch(NEXUS_DEVICE_STATE_UNKNOWN);
48
+ /** `CredentialInfo` (§4.1): the credential that made the request. */
49
+ export const nexusCloudCredentialSchema = z.object({
50
+ kind: z.enum(['device', 'session']),
51
+ credentialId: z.string().nullable().optional(),
52
+ profile: profile.optional(),
53
+ scopes: z.array(z.string()).default([]),
54
+ createdAt: isoTime.nullable().optional(),
55
+ lastUsedAt: isoTime.nullable().optional(),
56
+ /** When the credential expires if it is not used again; null for sessions. */
57
+ idleExpiresAt: isoTime.nullable().optional(),
58
+ });
59
+ /** `DeviceView` (§4.1), as far as the CLI reports it. E2 sends a subset. */
60
+ export const nexusCloudDeviceSchema = z.object({
61
+ deviceId: z.string(),
62
+ name: z.string(),
63
+ platform: z.string().optional(),
64
+ arch: z.string().nullable().optional(),
65
+ cliVersion: z.string().nullable().optional(),
66
+ createdAt: isoTime.optional(),
67
+ lastSeenAt: isoTime.nullable().optional(),
68
+ state: deviceState,
69
+ signedOutAt: isoTime.nullable().optional(),
70
+ /** Base64 device certificate; null until the device holds a key grant. */
71
+ certificate: z.string().nullable().optional(),
72
+ /** The current credential's profile, or null with none (signed out or revoked). */
73
+ profile: profile.optional(),
74
+ /** True for the device whose credential made this request. */
75
+ current: z.boolean().default(false),
76
+ projects: z.number().int().nonnegative().optional(),
77
+ replicas: z.number().int().nonnegative().optional(),
78
+ lastSyncAt: isoTime.nullable().optional(),
79
+ lastPresenceAt: isoTime.nullable().optional(),
80
+ });
81
+ /** `OrganizationSummary` (§4.1). */
82
+ export const nexusCloudOrganizationSchema = z.object({
83
+ id: z.string(),
84
+ name: z.string(),
85
+ slug: z.string().nullable().optional(),
86
+ role: z.string().optional(),
87
+ personal: z.boolean().optional(),
88
+ });
89
+ /** `AccountUser` (§4.1). */
90
+ export const nexusCloudUserSchema = z.object({
91
+ id: z.string(),
92
+ email: z.string(),
93
+ name: z.string().nullable().optional(),
94
+ });
95
+ /** `Whoami` (E2 `GET /v1/whoami`). */
96
+ export const nexusCloudWhoamiSchema = z.object({
97
+ serverTime: isoTime.optional(),
98
+ user: nexusCloudUserSchema,
99
+ organizations: z.array(nexusCloudOrganizationSchema).default([]),
100
+ credential: nexusCloudCredentialSchema,
101
+ /** The calling device; null for a session caller. */
102
+ device: nexusCloudDeviceSchema.nullable(),
103
+ });
104
+ /** `ListDevicesViewResult` (E5 `GET /v1/devices`), one page. */
105
+ export const nexusCloudDevicePageSchema = z.object({
106
+ devices: z.array(nexusCloudDeviceSchema),
107
+ nextCursor: z.string().max(512).nullable().default(null),
108
+ truncated: z.boolean().default(false),
109
+ });
110
+ /** Path-free replica presence (`ReplicaPresence`), with the R4 `sync` flag; other fields kept as sent. */
111
+ export const nexusCloudPresenceSchema = z.looseObject({
112
+ observedAt: isoTime.optional(),
113
+ sync: z.object({ enabled: z.boolean() }).optional(),
114
+ });
115
+ /** `ReplicaRow` (§4.1). */
116
+ export const nexusCloudReplicaSchema = z.object({
117
+ projectId: z.string(),
118
+ replicaId: z.string(),
119
+ deviceId: z.string(),
120
+ deviceName: z.string(),
121
+ deviceState: deviceState.optional(),
122
+ attachedAt: isoTime.optional(),
123
+ lastSyncAt: isoTime.nullable(),
124
+ presence: nexusCloudPresenceSchema.nullable(),
125
+ presenceAt: isoTime.nullable(),
126
+ });
127
+ /** `DeviceCounts` (§4.1): distinct devices holding a replica. */
128
+ export const nexusCloudDeviceCountsSchema = z.object({
129
+ active: z.number().int().nonnegative(),
130
+ total: z.number().int().nonnegative(),
131
+ });
132
+ /** The project fields every project view carries (`Project`, §4.1). */
133
+ const projectFields = {
134
+ projectId: z.string(),
135
+ label: z.string().nullable(),
136
+ organizationId: z.string(),
137
+ organizationName: z.string().optional(),
138
+ remoteUrl: z.string().nullable().optional(),
139
+ createdAt: isoTime.optional(),
140
+ };
141
+ /** `ProjectListItem` (§4.1, E13). */
142
+ export const nexusCloudProjectListItemSchema = z.object({
143
+ ...projectFields,
144
+ role: z.string(),
145
+ streamId: z.string().optional(),
146
+ headSeq: z.number().int().nonnegative().nullable().optional(),
147
+ openConflicts: z.number().int().nonnegative().optional(),
148
+ replicas: z.array(nexusCloudReplicaSchema).default([]),
149
+ devices: nexusCloudDeviceCountsSchema.optional(),
150
+ replicaCount: z.number().int().nonnegative().optional(),
151
+ lastSyncAt: isoTime.nullable().optional(),
152
+ lastPresenceAt: isoTime.nullable().optional(),
153
+ /** This project's replica list was cut at 50 (T12858). */
154
+ replicasTruncated: z.boolean().default(false),
155
+ });
156
+ /** `ListProjectsResult` (E13 `GET /v1/projects`), one page. */
157
+ export const nexusCloudProjectPageSchema = z.object({
158
+ projects: z.array(nexusCloudProjectListItemSchema),
159
+ nextCursor: z.string().max(512).nullable().default(null),
160
+ /** Anything in the page was cut (the project list or a replica list). */
161
+ truncated: z.boolean().default(false),
162
+ /** The project list itself was cut at 1000 (T12858). */
163
+ projectsTruncated: z.boolean().default(false),
164
+ });
165
+ /** `ProjectDetail` (E14 `GET /v1/projects/:projectId`). */
166
+ export const nexusCloudProjectDetailSchema = z.object({
167
+ project: z.object({ ...projectFields, deletedAt: isoTime.nullable().optional() }),
168
+ role: z.string(),
169
+ canTrash: z.boolean().optional(),
170
+ openConflicts: z.number().int().nonnegative(),
171
+ /** At most 50, oldest attachment first. */
172
+ replicas: z.array(nexusCloudReplicaSchema),
173
+ devices: nexusCloudDeviceCountsSchema,
174
+ replicaCount: z.number().int().nonnegative().optional(),
175
+ lastSyncAt: isoTime.nullable().optional(),
176
+ /** `replicas` was cut at 50. */
177
+ truncated: z.boolean().default(false),
178
+ stream: z
179
+ .object({
180
+ streamId: z.string(),
181
+ headSeq: z.number().int().nonnegative(),
182
+ headCheckpointId: z.string().nullable(),
183
+ })
184
+ .nullable(),
185
+ });
186
+ /** `ListReplicasResult` (E15 `GET /v1/projects/:projectId/replicas`), one page. */
187
+ export const nexusCloudReplicaPageSchema = z.object({
188
+ replicas: z.array(nexusCloudReplicaSchema),
189
+ devices: nexusCloudDeviceCountsSchema.optional(),
190
+ nextCursor: z.string().max(512).nullable().default(null),
191
+ truncated: z.boolean().default(false),
192
+ });
193
+ // ---------- status (E3, §4.4) ----------
194
+ /** E3 check ids, in their contract order (§4.1 `StatusCheckId`). */
195
+ export const NEXUS_STATUS_CHECK_IDS = [
196
+ 'credential.valid',
197
+ 'device.registered',
198
+ 'device.active',
199
+ 'device.certified',
200
+ 'project.registered',
201
+ 'project.writable',
202
+ 'replica.attached',
203
+ 'presence.fresh',
204
+ 'replica.synced',
205
+ 'conflicts.none',
206
+ ];
207
+ /** The server's verdicts (§4.1 `StatusVerdict`). */
208
+ export const NEXUS_STATUS_VERDICTS = ['ok', 'attention', 'not-linked', 'not-registered'];
209
+ /** `cleo cloud status` verdicts: the server's plus the local `not-signed-in` (§4.4). */
210
+ export const CLOUD_STATUS_VERDICTS = [...NEXUS_STATUS_VERDICTS, 'not-signed-in'];
211
+ const knownCheckId = z.enum(NEXUS_STATUS_CHECK_IDS);
212
+ /** `StatusCheck` (§4.1). Only required checks drive the verdict. */
213
+ export const nexusCloudStatusCheckSchema = z.object({
214
+ id: z.enum(NEXUS_STATUS_CHECK_IDS),
215
+ ok: z.boolean(),
216
+ required: z.boolean(),
217
+ detail: z.string(),
218
+ });
219
+ /** `NexusStatus` (E3 `GET /v1/status`). */
220
+ export const nexusCloudStatusSchema = z.object({
221
+ serverTime: isoTime.optional(),
222
+ apiVersion: z.string().optional(),
223
+ user: nexusCloudUserSchema,
224
+ credential: nexusCloudCredentialSchema,
225
+ device: nexusCloudDeviceSchema.nullable(),
226
+ project: z
227
+ .object({
228
+ projectId: z.string(),
229
+ registered: z.boolean(),
230
+ organizationId: z.string().nullable(),
231
+ organizationName: z.string().nullable(),
232
+ role: z.string().nullable(),
233
+ })
234
+ .nullable(),
235
+ replica: z
236
+ .object({
237
+ replicaId: z.string(),
238
+ attached: z.boolean(),
239
+ attachedElsewhere: z.boolean(),
240
+ attachedAt: isoTime.nullable(),
241
+ lastSyncAt: isoTime.nullable(),
242
+ presenceAt: isoTime.nullable(),
243
+ lastReplicaSeq: z.number().int().nonnegative().nullable().optional(),
244
+ })
245
+ .nullable(),
246
+ stream: z
247
+ .object({
248
+ streamId: z.string(),
249
+ headSeq: z.number().int().nonnegative(),
250
+ headCheckpointId: z.string().nullable(),
251
+ openConflicts: z.number().int().nonnegative(),
252
+ devices: nexusCloudDeviceCountsSchema,
253
+ })
254
+ .nullable(),
255
+ /** Check ids added by a newer server are dropped, never a parse failure. */
256
+ checks: z.array(nexusCloudStatusCheckSchema.extend({ id: z.string() })).transform((list) => list.flatMap((c) => {
257
+ const id = knownCheckId.safeParse(c.id);
258
+ return id.success ? [{ ...c, id: id.data }] : [];
259
+ })),
260
+ /** A verdict added by a newer server reads as `attention`: never `ok` by accident. */
261
+ verdict: z.enum(NEXUS_STATUS_VERDICTS).catch('attention'),
262
+ });
263
+ // ---------- error mapping (§4.0.4) ----------
264
+ /** `details.reason` values of a 401 (§4.0.4 `UnauthenticatedReason`). */
265
+ export const NEXUS_UNAUTHENTICATED_REASONS = [
266
+ 'missing',
267
+ 'invalid',
268
+ 'credential-revoked',
269
+ 'credential-expired',
270
+ 'device-signed-out',
271
+ 'device-revoked',
272
+ 'session-bearer-retired',
273
+ 'session-used',
274
+ ];
275
+ /** `details.reason` values of a 403 (§4.0.4 `ForbiddenReason`). */
276
+ export const NEXUS_FORBIDDEN_REASONS = [
277
+ 'insufficient-scope',
278
+ 'session-required',
279
+ 'device-required',
280
+ 'device-mismatch',
281
+ 'not-self',
282
+ 'project-role',
283
+ 'route-undeclared',
284
+ 'bearer-session-required',
285
+ 'session-not-fresh',
286
+ 'device-limit',
287
+ ];
288
+ /** `details.revokedReason` values of a 401 `credential-revoked` (§4.0.4, v2.11). */
289
+ export const NEXUS_REVOKED_REASONS = ['signed-out', 'revoked', 'rotated', 'reenrolled'];
290
+ const LOGIN = 'run `cleo login nexus`';
291
+ const COMPROMISED = {
292
+ code: 'E_NEXUS_CREDENTIAL_COMPROMISED',
293
+ message: "this device's credential was replaced or revoked elsewhere, possibly used from another machine",
294
+ fix: 'revoke this device on cleocode.dev and sign in again with `cleo login nexus`',
295
+ };
296
+ const DEVICE_REVOKED = {
297
+ code: 'E_NEXUS_DEVICE_REVOKED',
298
+ message: 'this device was revoked',
299
+ fix: 'run `cleo login nexus` to enrol this machine as a new device',
300
+ };
301
+ const SESSION_EXPIRED_LOGIN = {
302
+ code: 'E_NEXUS_SESSION_EXPIRED',
303
+ message: 'the session is too old for this request',
304
+ fix: 'run `cleo login nexus` (needs a browser: on a headless machine a human must complete the login)',
305
+ };
306
+ const SERVER_REFUSED = {
307
+ code: 'E_NEXUS_REQUEST_FAILED',
308
+ message: null,
309
+ fix: null,
310
+ };
311
+ /**
312
+ * 401 `credential-revoked`, by `details.revokedReason` (§4.0.4 v2.11). An
313
+ * absent or unknown reason maps as `rotated`: a revocation the CLI cannot
314
+ * explain (R2).
315
+ */
316
+ export const NEXUS_REVOKED_REASON_ERRORS = {
317
+ reenrolled: {
318
+ code: 'E_NEXUS_NOT_SIGNED_IN',
319
+ message: "this device's credential was replaced by a newer login of the same device",
320
+ fix: LOGIN,
321
+ },
322
+ 'signed-out': {
323
+ code: 'E_NEXUS_NOT_SIGNED_IN',
324
+ message: 'this device was signed out and later signed in again with another credential',
325
+ fix: LOGIN,
326
+ },
327
+ revoked: DEVICE_REVOKED,
328
+ rotated: COMPROMISED,
329
+ };
330
+ /** 401 `E_UNAUTHENTICATED`, by `details.reason` (§4.0.4). Unknown reasons map as `invalid`. */
331
+ export const NEXUS_UNAUTHENTICATED_ERRORS = {
332
+ missing: {
333
+ code: 'E_NEXUS_NOT_SIGNED_IN',
334
+ message: 'not signed in to Cleo Nexus (the credential is missing or invalid)',
335
+ fix: LOGIN,
336
+ },
337
+ invalid: {
338
+ code: 'E_NEXUS_NOT_SIGNED_IN',
339
+ message: 'not signed in to Cleo Nexus (the credential is missing or invalid)',
340
+ fix: LOGIN,
341
+ },
342
+ // Resolved by `details.revokedReason` through NEXUS_REVOKED_REASON_ERRORS.
343
+ 'credential-revoked': COMPROMISED,
344
+ 'credential-expired': {
345
+ code: 'E_NEXUS_SESSION_EXPIRED',
346
+ message: 'the device credential expired after 90 days without use',
347
+ fix: LOGIN,
348
+ },
349
+ 'device-signed-out': {
350
+ code: 'E_NEXUS_DEVICE_SIGNED_OUT',
351
+ message: 'this device was signed out',
352
+ fix: LOGIN,
353
+ },
354
+ 'device-revoked': DEVICE_REVOKED,
355
+ 'session-bearer-retired': {
356
+ code: 'E_NEXUS_SESSION_EXPIRED',
357
+ message: 'bearer sessions are no longer accepted',
358
+ fix: 'run `cleo login nexus` with the current CLI',
359
+ },
360
+ 'session-used': {
361
+ code: 'E_NEXUS_SESSION_EXPIRED',
362
+ message: 'the 9.24 session was already used by another enrolment',
363
+ fix: LOGIN,
364
+ },
365
+ };
366
+ /** 403 `E_FORBIDDEN`, by `details.reason` (§4.0.4). Unknown reasons are reported as sent. */
367
+ export const NEXUS_FORBIDDEN_ERRORS = {
368
+ 'insufficient-scope': {
369
+ code: 'E_NEXUS_INSUFFICIENT_SCOPE',
370
+ message: "this device's credential lacks the scope for that request",
371
+ fix: 'run `cleo login nexus` without --read-only to enrol with the full device profile',
372
+ },
373
+ 'session-required': SERVER_REFUSED,
374
+ 'device-required': SERVER_REFUSED,
375
+ 'device-mismatch': SERVER_REFUSED,
376
+ 'not-self': SERVER_REFUSED,
377
+ 'project-role': SERVER_REFUSED,
378
+ 'route-undeclared': SERVER_REFUSED,
379
+ 'bearer-session-required': SESSION_EXPIRED_LOGIN,
380
+ 'session-not-fresh': SESSION_EXPIRED_LOGIN,
381
+ 'device-limit': {
382
+ code: 'E_NEXUS_REQUEST_FAILED',
383
+ message: 'the account has reached its device limit',
384
+ fix: 'revoke unused devices on cleocode.dev, then retry',
385
+ },
386
+ };
387
+ /**
388
+ * 409 `E_CONFLICT` reasons the CLI reports with their own code (§4.0.4). Every
389
+ * other conflict is either handled inside its flow or reported as
390
+ * `E_NEXUS_REQUEST_FAILED` with the server's message.
391
+ */
392
+ export const NEXUS_CONFLICT_ERRORS = {
393
+ 'replica-copied': {
394
+ code: 'E_NEXUS_REPLICA_COPIED',
395
+ message: 'this project store is attached from another device (a copied store)',
396
+ fix: null,
397
+ },
398
+ 'rotation-conflict': COMPROMISED,
399
+ };
400
+ /** No answer at all (network error or timeout, §4.0.4). */
401
+ export const NEXUS_UNREACHABLE_ERROR = {
402
+ code: 'E_NEXUS_UNREACHABLE',
403
+ message: null,
404
+ fix: 'check your network and retry',
405
+ };
406
+ //# sourceMappingURL=nexus-cloud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nexus-cloud.js","sourceRoot":"","sources":["../src/nexus-cloud.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/contracts",
3
- "version": "2026.9.26",
3
+ "version": "2026.10.1",
4
4
  "description": "Domain types, interfaces, and contracts for the CLEO ecosystem",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -198,7 +198,7 @@
198
198
  "dependencies": {
199
199
  "zod": "^4.3.6",
200
200
  "zod-to-json-schema": "^3.25.2",
201
- "@cleocode/lafs": "2026.9.26"
201
+ "@cleocode/lafs": "2026.10.1"
202
202
  },
203
203
  "scripts": {
204
204
  "build": "tsc -b --force && node scripts/copy-assets.mjs && node scripts/emit-schemas.mjs",
package/src/index.ts CHANGED
@@ -2993,11 +2993,15 @@ export type {
2993
2993
  NexusAccountOrganization,
2994
2994
  NexusAccountStatus,
2995
2995
  NexusAccountUser,
2996
+ NexusDeviceEndOutcome,
2997
+ NexusDeviceLogoutResult,
2998
+ NexusDeviceLogoutRow,
2996
2999
  NexusLoginDevice,
2997
3000
  NexusLoginResult,
2998
3001
  NexusLogoutResult,
2999
3002
  NexusProjectLink,
3000
3003
  NexusProjectLinkResult,
3004
+ NexusReplicaAttachment,
3001
3005
  NexusSessionState,
3002
3006
  } from './nexus-account.js';
3003
3007
  export {
@@ -3009,4 +3013,64 @@ export {
3009
3013
  nexusAccountOrganizationSchema,
3010
3014
  nexusAccountUserSchema,
3011
3015
  } from './nexus-account.js';
3016
+ export type {
3017
+ CloudDevicesResult,
3018
+ CloudPaging,
3019
+ CloudProjectShowResult,
3020
+ CloudProjectsResult,
3021
+ CloudStatusLocal,
3022
+ CloudStatusOfflineDetails,
3023
+ CloudStatusResult,
3024
+ CloudStatusSummary,
3025
+ CloudStatusVerdict,
3026
+ CloudWarning,
3027
+ CloudWhoamiResult,
3028
+ NexusCloudCredential,
3029
+ NexusCloudDevice,
3030
+ NexusCloudDeviceCounts,
3031
+ NexusCloudProjectDetail,
3032
+ NexusCloudProjectListItem,
3033
+ NexusCloudReplica,
3034
+ NexusCloudStatus,
3035
+ NexusCloudStatusCheck,
3036
+ NexusCloudWhoami,
3037
+ NexusDeviceListState,
3038
+ NexusErrorMapping,
3039
+ NexusStatusCheckId,
3040
+ } from './nexus-cloud.js';
3041
+ export {
3042
+ CLOUD_STATUS_VERDICTS,
3043
+ NEXUS_CLOUD_MAX_PAGES,
3044
+ NEXUS_CLOUD_PROFILES,
3045
+ NEXUS_CONFLICT_ERRORS,
3046
+ NEXUS_DEVICE_LIST_STATES,
3047
+ NEXUS_DEVICE_STATE_UNKNOWN,
3048
+ NEXUS_DEVICE_STATES,
3049
+ NEXUS_FORBIDDEN_ERRORS,
3050
+ NEXUS_FORBIDDEN_REASONS,
3051
+ NEXUS_PAGE_LIMIT_MAX,
3052
+ NEXUS_PRESENCE_FRESH_SECONDS,
3053
+ NEXUS_REVOKED_REASON_ERRORS,
3054
+ NEXUS_REVOKED_REASONS,
3055
+ NEXUS_STATUS_CHECK_IDS,
3056
+ NEXUS_STATUS_VERDICTS,
3057
+ NEXUS_UNAUTHENTICATED_ERRORS,
3058
+ NEXUS_UNAUTHENTICATED_REASONS,
3059
+ NEXUS_UNREACHABLE_ERROR,
3060
+ nexusCloudCredentialSchema,
3061
+ nexusCloudDeviceCountsSchema,
3062
+ nexusCloudDevicePageSchema,
3063
+ nexusCloudDeviceSchema,
3064
+ nexusCloudOrganizationSchema,
3065
+ nexusCloudPresenceSchema,
3066
+ nexusCloudProjectDetailSchema,
3067
+ nexusCloudProjectListItemSchema,
3068
+ nexusCloudProjectPageSchema,
3069
+ nexusCloudReplicaPageSchema,
3070
+ nexusCloudReplicaSchema,
3071
+ nexusCloudStatusCheckSchema,
3072
+ nexusCloudStatusSchema,
3073
+ nexusCloudUserSchema,
3074
+ nexusCloudWhoamiSchema,
3075
+ } from './nexus-cloud.js';
3012
3076
  export { isStorableTaskId, isTaskId, TASK_ID_REGEX, type TaskId } from './task-id.js';
@@ -65,8 +65,10 @@ export const NEXUS_ACCOUNT_ERROR_CODES = [
65
65
  'E_NEXUS_BUSY',
66
66
  /** Several accounts hold a device credential on one origin and none was named. */
67
67
  'E_NEXUS_ACCOUNT_AMBIGUOUS',
68
- /** An option that needs device credentials (`--read-only`) without `CLEO_NEXUS_DEVICE=1`. */
68
+ /** An option that needs device credentials (`--read-only`) with `CLEO_NEXUS_DEVICE=0`. */
69
69
  'E_NEXUS_DEVICE_REQUIRED',
70
+ /** `.cleo/nexus-link.json` is in a format this CLEO cannot update (written by a newer CLEO). */
71
+ 'E_NEXUS_LINK_FILE_UNSUPPORTED',
70
72
  ] as const;
71
73
 
72
74
  /** One of {@link NEXUS_ACCOUNT_ERROR_CODES}. */
@@ -161,9 +163,9 @@ export interface NexusLoginResult {
161
163
  credentialsPath: string;
162
164
  /** Non-fatal problems, e.g. the account lookup failed after a good login. */
163
165
  warnings: string[];
164
- /** The enrolled device; present only with `CLEO_NEXUS_DEVICE=1` (device credentials). */
166
+ /** The enrolled device; present only with device credentials (the default; off with `CLEO_NEXUS_DEVICE=0`). */
165
167
  device?: NexusLoginDevice;
166
- /** Scopes of the stored device credential; present only with `CLEO_NEXUS_DEVICE=1`. */
168
+ /** Scopes of the stored device credential; present only with device credentials. */
167
169
  scopes?: string[];
168
170
  }
169
171
 
@@ -184,6 +186,56 @@ export interface NexusLogoutResult {
184
186
  warnings: string[];
185
187
  }
186
188
 
189
+ /**
190
+ * What happened to one device's sign-out (E9) or revoke (E10) in
191
+ * `cleo logout nexus [--revoke]` with device credentials (the default; `CLEO_NEXUS_DEVICE=0` turns them off) (cleo-nexus
192
+ * device contract §3.5, M3). Holds no secret.
193
+ *
194
+ * - `confirmed`: the server answered 200, or 401 `device-signed-out` /
195
+ * `device-revoked` (a revoke accepts only `device-revoked`);
196
+ * - `pending`: no usable answer (network, timeout, 429, 5xx, or a route the
197
+ * server does not have yet); the credentials stay in their slot and the
198
+ * next `cleo logout nexus`, `cleo login nexus` or cloud command retries;
199
+ * - `unconfirmed`: every credential held was refused as stale, so the CLI
200
+ * cannot finish it; the slot is kept, and a sign-out or revoke of the
201
+ * device on cleocode.dev lets the next retry confirm it;
202
+ * - `signed-out`: a revoke found the device already signed out (E10 401
203
+ * `device-signed-out`). Its credentials are dead, so the CLI cannot revoke
204
+ * it; the revoke slot is cleared (never retried) and the device must be
205
+ * revoked on cleocode.dev.
206
+ */
207
+ export type NexusDeviceEndOutcome = 'confirmed' | 'pending' | 'unconfirmed' | 'signed-out';
208
+
209
+ /** One device row of a {@link NexusDeviceLogoutResult}. */
210
+ export interface NexusDeviceLogoutRow {
211
+ /** Nexus user id of the entry. */
212
+ userId: string;
213
+ /** The device the request ended. */
214
+ deviceId: string;
215
+ /** `sign-out` (E9) or `revoke` (E10). */
216
+ action: 'sign-out' | 'revoke';
217
+ /** `true` for a replaced device's leftover request retried from `retired`. */
218
+ retired: boolean;
219
+ /** Server-side outcome. */
220
+ outcome: NexusDeviceEndOutcome;
221
+ /** `true` when a confirmed revoke removed the (origin, user) entry from `nexus-device.json`. */
222
+ removedLocally: boolean;
223
+ }
224
+
225
+ /** Result of `cleo logout nexus [--revoke]` with device credentials. Holds no secret. */
226
+ export interface NexusDeviceLogoutResult {
227
+ /** API origin. */
228
+ apiUrl: string;
229
+ /** `sign-out` or `revoke` (`--revoke`). */
230
+ action: 'sign-out' | 'revoke';
231
+ /** One row per device request settled or retried in this run, sorted by user then device. */
232
+ devices: NexusDeviceLogoutRow[];
233
+ /** The 9.24 session sign-out, when a leftover session was found for the origin. */
234
+ session: NexusLogoutResult | null;
235
+ /** Non-fatal problems: every non-`confirmed` row is named here. */
236
+ warnings: string[];
237
+ }
238
+
187
239
  /**
188
240
  * The binding of a local CLEO project to its Nexus registration, persisted in
189
241
  * the project's machine-local `.cleo/nexus-link.json`, keyed by API origin.
@@ -203,6 +255,31 @@ export interface NexusProjectLink {
203
255
  streamId: string;
204
256
  /** ISO time of the last successful link. */
205
257
  linkedAt: string;
258
+ /**
259
+ * This store's replica id as attached on the server (device contract
260
+ * §3.6, §3.7). A cache, not the source of truth: the store's active
261
+ * `_sync_replica` row is. Absent before the first device-credential link.
262
+ */
263
+ replicaId?: string;
264
+ /** The Nexus device id that attached {@link NexusProjectLink.replicaId}. */
265
+ nexusDeviceId?: string;
266
+ /** ISO time the replica was last attached or confirmed. */
267
+ attachedAt?: string;
268
+ }
269
+
270
+ /**
271
+ * What `cleo project link` did for this machine's copy of the project with a
272
+ * device credential (contract §3.6 steps 3 to 5). Holds no path or secret.
273
+ */
274
+ export interface NexusReplicaAttachment {
275
+ /** The store's replica id (UUIDv7), now attached on the server. */
276
+ replicaId: string;
277
+ /** The Nexus device that holds it. */
278
+ deviceId: string;
279
+ /** The retired replica id when this link rebound the store (a copy, or a re-enrolled device). */
280
+ reboundFrom: string | null;
281
+ /** Server time the presence report was received, or `null` when sending it failed (see warnings). */
282
+ presenceAt: string | null;
206
283
  }
207
284
 
208
285
  /** Result of `cleo project link`. */
@@ -217,4 +294,17 @@ export interface NexusProjectLinkResult {
217
294
  alreadyLinked: boolean;
218
295
  /** Absolute path of the local binding file. */
219
296
  linkPath: string;
297
+ /**
298
+ * The replica attach and presence report, with device credentials; `null`
299
+ * with the 9.24 session (`CLEO_NEXUS_DEVICE=0`), which cannot attach.
300
+ */
301
+ replica: NexusReplicaAttachment | null;
302
+ /**
303
+ * Why this machine's copy was not attached, when device mode tried and
304
+ * failed (for example `E_NEXUS_REPLICA_COPIED`); `null` otherwise. The same
305
+ * text is also in {@link NexusProjectLinkResult.warnings}.
306
+ */
307
+ attachError: { code: string; message: string; fix: string | null } | null;
308
+ /** Non-fatal problems (for example, presence could not be sent). */
309
+ warnings: string[];
220
310
  }