@north-light/api 0.3.575 → 0.3.577
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/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/core/command-plugins/bundle.d.ts +6 -3
- package/dist/core/command-plugins/bundle.js +13 -16
- package/dist/core/io.js +1 -1
- package/dist/core/runtime/broker/daemon-ops.d.ts +4 -0
- package/dist/core/runtime/broker/daemon-ops.js +15 -2
- package/package.json +1 -1
package/dist/api/contract.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** The contract level this build serves and requires. Written by `scripts/contract.mjs release`; never edit by hand. */
|
|
2
|
-
export declare const CONTRACT_LEVEL = "1.
|
|
2
|
+
export declare const CONTRACT_LEVEL = "1.39";
|
|
3
3
|
/** Request header naming the one contract level the caller needs, e.g. `1.3`. Optional: absent means no check. */
|
|
4
4
|
export declare const REQUIRED_CONTRACT_HEADER = "Crouter-Required-Contract";
|
|
5
5
|
/** Response header listing the contract levels the server serves, comma-separated, one per major, e.g. `1.3`. */
|
package/dist/api/contract.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
//
|
|
13
13
|
// PURITY (spec §3.1): Node built-ins + `src/api/*` only.
|
|
14
14
|
/** The contract level this build serves and requires. Written by `scripts/contract.mjs release`; never edit by hand. */
|
|
15
|
-
export const CONTRACT_LEVEL = '1.
|
|
15
|
+
export const CONTRACT_LEVEL = '1.39';
|
|
16
16
|
/** Request header naming the one contract level the caller needs, e.g. `1.3`. Optional: absent means no check. */
|
|
17
17
|
export const REQUIRED_CONTRACT_HEADER = 'Crouter-Required-Contract';
|
|
18
18
|
/** Response header listing the contract levels the server serves, comma-separated, one per major, e.g. `1.3`. */
|
|
@@ -131,6 +131,9 @@ export interface InstallBundleArchiveOptions<M> {
|
|
|
131
131
|
/** Checked against the validated archive before anything is written; a
|
|
132
132
|
* returned message refuses the archive (a provider bundle naming another id). */
|
|
133
133
|
accept?: (bundle: ValidatedBundle) => string | undefined;
|
|
134
|
+
/** Default true. False leaves the config version and state validator unwritten: the caller keeps the install record itself
|
|
135
|
+
* (a cloud role's deployment-wide provider bundle has no person whose settings could hold it). */
|
|
136
|
+
record?: boolean;
|
|
134
137
|
}
|
|
135
138
|
export interface InstalledBundleArchive<M> {
|
|
136
139
|
manifest: PluginManifest;
|
|
@@ -140,9 +143,9 @@ export interface InstalledBundleArchive<M> {
|
|
|
140
143
|
staged: M;
|
|
141
144
|
}
|
|
142
145
|
/**
|
|
143
|
-
* Validate `raw`, stage it beside the package root, swap it in, then
|
|
144
|
-
* the config version and
|
|
145
|
-
*
|
|
146
|
+
* Validate `raw`, stage it beside the package root, swap it in, then (unless
|
|
147
|
+
* `record` is false) record the config version and state validator. A failure
|
|
148
|
+
* before the swap leaves the previous package untouched.
|
|
146
149
|
* The caller holds the plugin's swap lock (`bundleSwapLockPath`).
|
|
147
150
|
*/
|
|
148
151
|
export declare function installBundleArchive<M>(name: string, raw: Uint8Array, options: InstallBundleArchiveOptions<M>): Promise<InstalledBundleArchive<M>>;
|
|
@@ -517,9 +517,9 @@ export function writeStagedBundle(stagingRoot, manifest, bundle) {
|
|
|
517
517
|
syncTree(stagingRoot);
|
|
518
518
|
}
|
|
519
519
|
/**
|
|
520
|
-
* Validate `raw`, stage it beside the package root, swap it in, then
|
|
521
|
-
* the config version and
|
|
522
|
-
*
|
|
520
|
+
* Validate `raw`, stage it beside the package root, swap it in, then (unless
|
|
521
|
+
* `record` is false) record the config version and state validator. A failure
|
|
522
|
+
* before the swap leaves the previous package untouched.
|
|
523
523
|
* The caller holds the plugin's swap lock (`bundleSwapLockPath`).
|
|
524
524
|
*/
|
|
525
525
|
export async function installBundleArchive(name, raw, options) {
|
|
@@ -590,18 +590,15 @@ export async function installBundleArchive(name, raw, options) {
|
|
|
590
590
|
finally {
|
|
591
591
|
removePath(staging);
|
|
592
592
|
}
|
|
593
|
-
//
|
|
594
|
-
//
|
|
595
|
-
//
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
cfg.plugins[name] = { enabled: options.enable ? true : (cfg.plugins[name]?.enabled ?? true), version };
|
|
604
|
-
});
|
|
605
|
-
await recordCheckedGeneration(scope, name, options.etag, { swapped: true });
|
|
593
|
+
// For ordinary installs: directory swap, then config version, then state validator. A process killed mid-sequence leaves the
|
|
594
|
+
// ledger naming an older generation than the disk, which the next check repairs. A cloud-role provider bundle has no person's
|
|
595
|
+
// settings to update; its caller records the validator after the swap in the deployment's plugin directory instead.
|
|
596
|
+
if (options.record !== false) {
|
|
597
|
+
await ensureScopeInitialized(scope, scopeRootPath);
|
|
598
|
+
await updateConfig(scope, (cfg) => {
|
|
599
|
+
cfg.plugins[name] = { enabled: options.enable ? true : (cfg.plugins[name]?.enabled ?? true), version };
|
|
600
|
+
});
|
|
601
|
+
await recordCheckedGeneration(scope, name, options.etag, { swapped: true });
|
|
602
|
+
}
|
|
606
603
|
return { manifest, validated, version, root, staged };
|
|
607
604
|
}
|
package/dist/core/io.js
CHANGED
|
@@ -360,7 +360,7 @@ export function apiErrorToCliError(err, next, options = {}) {
|
|
|
360
360
|
? `Wait ${provider.retryAfterS}s, then retry; do not retry sooner.`
|
|
361
361
|
: err.status >= 500
|
|
362
362
|
? 'This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).'
|
|
363
|
-
: err.status === 404
|
|
363
|
+
: err.status === 404 && provider.code === undefined
|
|
364
364
|
? 'List nodes with `crtr node inspect list`.'
|
|
365
365
|
: 'Inspect the error and adjust the call. See -h for the schema.'),
|
|
366
366
|
};
|
|
@@ -44,6 +44,10 @@ export declare function acknowledgeBrokerMail(nodeId: string, deliveries: MailRe
|
|
|
44
44
|
export declare function recordBrokerTurn(nodeId: string, request: Omit<BrokerTurnRequest, 'expected_execution_id'>): Promise<BrokerTurnResultDTO>;
|
|
45
45
|
export declare function mutateBrokerProviderRetry(nodeId: string, request: Omit<BrokerProviderRetryRequest, 'expected_execution_id'>): Promise<BrokerProviderRetryResultDTO>;
|
|
46
46
|
export declare function mutateBrokerFault(nodeId: string, request: Omit<BrokerFaultRequest, 'expected_execution_id'>): Promise<BrokerFaultResultDTO>;
|
|
47
|
+
/** A conversation store that refused writes past its deadline: the node's durable fault, written (execution-fenced) before the broker
|
|
48
|
+
* exits so the control plane and a harness read the cause. The record is capped at 5 s: a failed or slow record is logged and the
|
|
49
|
+
* exit proceeds. */
|
|
50
|
+
export declare function recordConversationWriteFault(nodeId: string, error: unknown): Promise<void>;
|
|
47
51
|
export declare function brokerRecovery(nodeId: string): Promise<RecoveryStateDTO>;
|
|
48
52
|
/** Node-scoped fault writes are for non-broker clients such as attach transport.
|
|
49
53
|
* Broker-owned recovery mutations use the execution-fenced wrappers above. */
|
|
@@ -7,6 +7,7 @@ import { localClient } from '../../../api/node-transport.js';
|
|
|
7
7
|
import { ApiError } from '../../../api/errors.js';
|
|
8
8
|
import { envExecutionId } from '../../../shared/env.js';
|
|
9
9
|
import { brokerSignalClient } from './signal-stream.js';
|
|
10
|
+
import { emitEvent } from '../../events/emit.js';
|
|
10
11
|
import { cachedBrokerNodeFields } from '../../../daemon/broker-signals/bus.js';
|
|
11
12
|
import { fetchRunAttachments } from './attachments-fetch.js';
|
|
12
13
|
import { reportRefNodeId } from '../../../shared/inbox-entry-body.js';
|
|
@@ -153,15 +154,27 @@ export function mutateBrokerProviderRetry(nodeId, request) {
|
|
|
153
154
|
export function mutateBrokerFault(nodeId, request) {
|
|
154
155
|
return daemonClient().mutateBrokerFault(nodeId, { ...request, expected_execution_id: brokerExecutionId() });
|
|
155
156
|
}
|
|
157
|
+
/** A conversation store that refused writes past its deadline: the node's durable fault, written (execution-fenced) before the broker
|
|
158
|
+
* exits so the control plane and a harness read the cause. The record is capped at 5 s: a failed or slow record is logged and the
|
|
159
|
+
* exit proceeds. */
|
|
160
|
+
export async function recordConversationWriteFault(nodeId, error) {
|
|
161
|
+
const record = mutateBrokerFault(nodeId, {
|
|
162
|
+
op: 'record',
|
|
163
|
+
input: { link: 'daemon→node', op: 'conversation_write_failed', kind: 'other', retry: { disposition: 'manual' }, message: error instanceof Error ? error.message : String(error) },
|
|
164
|
+
});
|
|
165
|
+
await Promise.race([record, new Promise((_, reject) => setTimeout(() => reject(new Error('conversation_write_failed fault record timed out')), 5_000).unref())])
|
|
166
|
+
.catch((faultError) => emitEvent({ level: 'error', event: 'broker.daemon.operation.failed', node_id: nodeId, error: faultError, fields: { operation: 'conversation_write_fault_record' } }));
|
|
167
|
+
}
|
|
156
168
|
export function brokerRecovery(nodeId) {
|
|
157
169
|
return daemonClient().getBrokerRecovery(nodeId, brokerExecutionId());
|
|
158
170
|
}
|
|
159
171
|
/** Node-scoped fault writes are for non-broker clients such as attach transport.
|
|
160
172
|
* Broker-owned recovery mutations use the execution-fenced wrappers above. */
|
|
161
|
-
export function recordNodeFault(nodeId, input) {
|
|
173
|
+
export async function recordNodeFault(nodeId, input) {
|
|
174
|
+
// `async` so a process with no way to reach the API (no node token) rejects instead of throwing inside a socket handler.
|
|
162
175
|
return daemonClient().recordNodeFault(nodeId, input);
|
|
163
176
|
}
|
|
164
|
-
export function clearNodeFault(nodeId, opts = {}) {
|
|
177
|
+
export async function clearNodeFault(nodeId, opts = {}) {
|
|
165
178
|
return daemonClient().clearNodeFault(nodeId, {
|
|
166
179
|
...(opts.link === undefined ? {} : { link: opts.link }),
|
|
167
180
|
...(opts.preserveEpisode === undefined ? {} : { preserve_episode: opts.preserveEpisode }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/api",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.577",
|
|
4
4
|
"description": "Typed crtrd /v1 API contract — DTOs, route builders, the error contract, the CrtrClient, and the command-plugin manifest format. Zero runtime dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/api/index.js",
|