@nelsonlongxiang/dsh-open-a2a-net 0.6.31 → 0.6.32
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/README.md +4 -1
- package/README_zh.md +3 -0
- package/assets/nexusDist/assets/index-D5H8R8de.js +9 -0
- package/assets/nexusDist/assets/index-D9GYZyGZ.css +1 -0
- package/assets/nexusDist/index.html +2 -2
- package/cli/a2a.mjs +445 -57
- package/lib/a2a-client.js +9 -4
- package/lib/auth-observer.js +254 -0
- package/lib/blob-store.js +210 -0
- package/lib/card.js +4 -2
- package/lib/cli-deposit.js +122 -7
- package/lib/client.js +64 -64
- package/lib/client.js.map +1 -1
- package/lib/faces/admin.js +133 -43
- package/lib/faces/canvas-notify.js +12 -3
- package/lib/faces/files.js +155 -0
- package/lib/faces/nodes.js +171 -0
- package/lib/faces/session-log.js +162 -0
- package/lib/faces/wire.js +206 -39
- package/lib/index.js +809 -1720
- package/lib/joined-store.js +23 -0
- package/lib/ledger-conservation.js +97 -0
- package/lib/legacy/teams-bridge-inbound.js +156 -0
- package/lib/node-bind.js +534 -0
- package/lib/node-github.js +72 -0
- package/lib/node-self.js +453 -0
- package/lib/node-store.js +484 -0
- package/lib/node-tasks.js +342 -0
- package/lib/origin-claim.js +246 -0
- package/lib/peer-directory.js +134 -0
- package/lib/receipt.js +26 -1
- package/lib/skill/SKILL.md +3 -1
- package/lib/skill/references/cli.md +82 -3
- package/lib/skill/references/collaboration.md +126 -74
- package/lib/skill/references/discovery.md +29 -0
- package/lib/skill/references/intake.md +107 -0
- package/lib/skill/references/router.md +96 -0
- package/lib/skill/references/setup.md +2 -1
- package/lib/task-auth.js +483 -0
- package/lib/task-ledger.js +324 -12
- package/lib/team-store.js +24 -1
- package/lib/tools/act.js +383 -0
- package/lib/tools/files.js +201 -0
- package/lib/tools/info.js +684 -0
- package/lib/types/a2a-client.d.ts +10 -4
- package/lib/types/auth-observer.d.ts +110 -0
- package/lib/types/blob-store.d.ts +83 -0
- package/lib/types/cli-deposit.d.ts +38 -0
- package/lib/types/faces/admin.d.ts +14 -2
- package/lib/types/faces/canvas-notify.d.ts +4 -1
- package/lib/types/faces/files.d.ts +53 -0
- package/lib/types/faces/nodes.d.ts +69 -0
- package/lib/types/faces/session-log.d.ts +44 -0
- package/lib/types/faces/wire.d.ts +50 -5
- package/lib/types/index.d.ts +27 -0
- package/lib/types/joined-store.d.ts +9 -0
- package/lib/types/ledger-conservation.d.ts +77 -0
- package/lib/types/legacy/teams-bridge-inbound.d.ts +94 -0
- package/lib/types/node-bind.d.ts +220 -0
- package/lib/types/node-github.d.ts +35 -0
- package/lib/types/node-self.d.ts +178 -0
- package/lib/types/node-store.d.ts +180 -0
- package/lib/types/node-tasks.d.ts +121 -0
- package/lib/types/origin-claim.d.ts +119 -0
- package/lib/types/peer-directory.d.ts +39 -0
- package/lib/types/receipt.d.ts +12 -0
- package/lib/types/task-auth.d.ts +271 -0
- package/lib/types/task-ledger.d.ts +143 -6
- package/lib/types/team-store.d.ts +9 -0
- package/lib/types/tools/act.d.ts +52 -0
- package/lib/types/tools/files.d.ts +38 -0
- package/lib/types/tools/info.d.ts +102 -0
- package/lib/types/types.d.ts +6 -0
- package/nexus-stage/src/canvas-ops.ts +1 -1
- package/nexus-stage/src/federation.ts +1 -0
- package/nexus-stage/src/main.ts +41 -18
- package/nexus-stage/src/planning-member-handles.ts +34 -0
- package/nexus-stage/src/planning-mirror.ts +47 -3
- package/nexus-stage/src/planning-reachability.ts +28 -0
- package/nexus-stage/src/planning-types.ts +1 -1
- package/nexus-stage/src/planning-view.ts +29 -26
- package/nexus-stage/src/planning.css +4 -0
- package/nexus-stage/src/wb-directory.ts +13 -0
- package/nexus-stage/src/workbench.css +3 -0
- package/nexus-stage/src/workbench.ts +5 -1
- package/package.json +1 -1
- package/assets/nexusDist/assets/index-Dz8N80tI.css +0 -1
- package/assets/nexusDist/assets/index-jm-cFAhB.js +0 -9
|
@@ -13,6 +13,8 @@ export type A2aSchedule = (callback: () => void, delayMs: number) => () => void;
|
|
|
13
13
|
export type A2aFetch = (url: string, init: {
|
|
14
14
|
readonly method: 'GET' | 'POST';
|
|
15
15
|
readonly headers: Record<string, string>;
|
|
16
|
+
/** Optional fetch redirect policy; origin verification sets manual. */
|
|
17
|
+
readonly redirect?: 'follow' | 'error' | 'manual';
|
|
16
18
|
readonly body?: string;
|
|
17
19
|
readonly signal?: AbortSignal;
|
|
18
20
|
}) => Promise<{
|
|
@@ -35,11 +37,15 @@ export interface A2aClientOptions {
|
|
|
35
37
|
readonly cardCaller: string;
|
|
36
38
|
/**
|
|
37
39
|
* gh#9+gh#10 OriginClaim signer (docs/protocol/delivery-origin-auth.md):
|
|
38
|
-
* produces the
|
|
39
|
-
*
|
|
40
|
-
* absent ⇒ the caller stays at
|
|
40
|
+
* produces the envelope headers with the NODE'S CARD KEY, bound to the
|
|
41
|
+
* request's target URL and method. Present ⇒ every card GET and direct
|
|
42
|
+
* POST carries a verifiable origin claim; absent ⇒ the caller stays at
|
|
43
|
+
* the named-only posture (transition).
|
|
41
44
|
*/
|
|
42
|
-
readonly originClaim?: (
|
|
45
|
+
readonly originClaim?: (target: {
|
|
46
|
+
readonly url: string;
|
|
47
|
+
readonly method: string;
|
|
48
|
+
}) => Record<string, string>;
|
|
43
49
|
/** Delayed-callback seam (HTTP timeouts). */
|
|
44
50
|
readonly schedule: A2aSchedule;
|
|
45
51
|
/** HTTP seam. */
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { Admission, TaskAuthorization } from './task-auth.ts';
|
|
2
|
+
/** Ring size of both the version history and the affected-task entries. */
|
|
3
|
+
export declare const AUTH_HISTORY_CAP = 32;
|
|
4
|
+
/** Longest refusal text kept on an affected task (the faces' texts fit; a longer one is cut, flagged by `…`). */
|
|
5
|
+
export declare const AFFECTED_REASON_CAP = 400;
|
|
6
|
+
/** One recorded allowlist version and what it hashed. */
|
|
7
|
+
export interface AuthVersionEntry {
|
|
8
|
+
readonly version: string;
|
|
9
|
+
readonly at: number;
|
|
10
|
+
/** Why it was observed: `boot`, `joined`, `canvas`, `roster`, or `lazy` (a read noticed a change no hook reported — CLI expiry, config). */
|
|
11
|
+
readonly cause: string;
|
|
12
|
+
/** The canonical inputs (task-auth.ts canonicalAllowlist), parsed. */
|
|
13
|
+
readonly inputs: unknown;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* One task's re-judgement. `basis-changed`: still admitted, but on teams that
|
|
17
|
+
* no longer overlap the record's; `would-revoke`: today's records refuse the
|
|
18
|
+
* caller — `reason` is that refusal text.
|
|
19
|
+
*/
|
|
20
|
+
export interface AffectedTask {
|
|
21
|
+
readonly taskId: string;
|
|
22
|
+
readonly direction: 'inbound' | 'outbound';
|
|
23
|
+
readonly caller: string;
|
|
24
|
+
readonly target: string;
|
|
25
|
+
readonly verdict: 'basis-changed' | 'would-revoke';
|
|
26
|
+
readonly reason: string;
|
|
27
|
+
}
|
|
28
|
+
/** One observation that found affected tasks. */
|
|
29
|
+
export interface AffectedEntry {
|
|
30
|
+
readonly at: number;
|
|
31
|
+
/** The previously recorded version; null when there was no history yet. */
|
|
32
|
+
readonly from_version: string | null;
|
|
33
|
+
readonly to_version: string;
|
|
34
|
+
readonly cause: string;
|
|
35
|
+
readonly tasks: readonly AffectedTask[];
|
|
36
|
+
}
|
|
37
|
+
/** The minimum of a ledger row the judgement reads. */
|
|
38
|
+
export interface JudgedRow {
|
|
39
|
+
readonly taskId: string;
|
|
40
|
+
readonly direction?: 'inbound' | 'outbound';
|
|
41
|
+
readonly auth?: TaskAuthorization;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Re-judge rows against today's records — pure: `judge` must be a read-only
|
|
45
|
+
* admission decision (task-auth.ts callerAdmission over the live records).
|
|
46
|
+
* A row is judged when it carries a record and either was born under another
|
|
47
|
+
* version than `version` or `cacheResting(row)` says its admission rests on
|
|
48
|
+
* the peer-card cache (`peer-org`, which the version does not hash; by
|
|
49
|
+
* default: the birth record's `via`).
|
|
50
|
+
* @returns the affected rows, in ledger order; unaffected rows are omitted.
|
|
51
|
+
*/
|
|
52
|
+
export declare function judgeAffected(rows: readonly JudgedRow[], version: string, judge: (caller: string, target: string, ingress: 'wire' | 'local') => Admission, cacheResting?: (row: JudgedRow) => boolean): AffectedTask[];
|
|
53
|
+
/** What one {@link AuthObserver.observe} call needs from the host. */
|
|
54
|
+
export interface ObserveInput {
|
|
55
|
+
readonly version: string;
|
|
56
|
+
/** The canonical inputs the version hashed (recorded with a new version). */
|
|
57
|
+
readonly inputs: () => unknown;
|
|
58
|
+
readonly cause: string;
|
|
59
|
+
readonly rows: () => readonly JudgedRow[];
|
|
60
|
+
readonly judge: (caller: string, target: string, ingress: 'wire' | 'local') => Admission;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The persisted observer. One instance per host; every entry point is
|
|
64
|
+
* total and never throws (an unwritable home degrades to memory-only).
|
|
65
|
+
*/
|
|
66
|
+
export declare class AuthObserver {
|
|
67
|
+
private readonly path;
|
|
68
|
+
private readonly now;
|
|
69
|
+
private versions;
|
|
70
|
+
private affected;
|
|
71
|
+
/**
|
|
72
|
+
* The last report per task ({@link reportKey}), so a task still affected
|
|
73
|
+
* the same way is not listed again — on a peer-org recheck poll, nor on a
|
|
74
|
+
* later unrelated version move. A task judged unaffected is forgotten, so
|
|
75
|
+
* a relapse reports again; a task gone from the rows is pruned.
|
|
76
|
+
* Boot-local by design: after a restart the next version change reports
|
|
77
|
+
* afresh.
|
|
78
|
+
*/
|
|
79
|
+
private readonly reported;
|
|
80
|
+
/**
|
|
81
|
+
* The rule of each task's latest passing judgement. Whether a row rests on
|
|
82
|
+
* the peer-card cache is read from here first, the birth record second: a
|
|
83
|
+
* row born remote-ref-samezone that today passes only through `peer-org`
|
|
84
|
+
* is rechecked like one born there (and stops being once a firm rule
|
|
85
|
+
* admits it again).
|
|
86
|
+
*/
|
|
87
|
+
private readonly lastRule;
|
|
88
|
+
constructor(path: string, now?: () => number);
|
|
89
|
+
/** The version history, newest first. */
|
|
90
|
+
history(): readonly AuthVersionEntry[];
|
|
91
|
+
/** The affected-task entries, newest first. */
|
|
92
|
+
entries(): readonly AffectedEntry[];
|
|
93
|
+
/**
|
|
94
|
+
* Record the current version when it moved, and re-judge.
|
|
95
|
+
* - Version moved: append it to the history; judge every row born under
|
|
96
|
+
* another version and every cache-resting row.
|
|
97
|
+
* - Version unchanged: only cache-resting rows are re-judged.
|
|
98
|
+
* - Cause `boot`: cache-resting rows are not judged at all — the peer-card
|
|
99
|
+
* cache is empty at boot, so every one of them would read as refused.
|
|
100
|
+
* The first read after boot (`lazy`) rechecks them.
|
|
101
|
+
* Either way a task is reported only when its report differs from the
|
|
102
|
+
* last one for it ({@link reportKey}).
|
|
103
|
+
* @returns the new affected entry, or undefined when nothing was affected.
|
|
104
|
+
*/
|
|
105
|
+
observe(input: ObserveInput): AffectedEntry | undefined;
|
|
106
|
+
/** Forget the per-task memory of tasks no longer among the unsettled rows. */
|
|
107
|
+
private prune;
|
|
108
|
+
private restore;
|
|
109
|
+
private persist;
|
|
110
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** One file's ceiling, in bytes (64 MiB; design §8). */
|
|
2
|
+
export declare const BLOB_FILE_MAX: number;
|
|
3
|
+
/** The store's ceiling, in bytes (1 GiB). */
|
|
4
|
+
export declare const BLOB_TOTAL_MAX: number;
|
|
5
|
+
/** The store's ceiling, in blobs. */
|
|
6
|
+
export declare const BLOB_COUNT_MAX = 256;
|
|
7
|
+
/** How long a grant lets its target pull (24h). */
|
|
8
|
+
export declare const BLOB_GRANT_TTL_MS: number;
|
|
9
|
+
/** A sanitized file name's length cap. */
|
|
10
|
+
export declare const BLOB_NAME_MAX = 120;
|
|
11
|
+
/** One grant: `to` may pull `sha256` until `expiresAt`. */
|
|
12
|
+
export interface BlobGrant {
|
|
13
|
+
readonly sha256: string;
|
|
14
|
+
readonly size: number;
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/** The target team or handle, exactly as the sender routed to it. */
|
|
17
|
+
readonly to: string;
|
|
18
|
+
/** The staging session (or CLI handle). */
|
|
19
|
+
readonly by: string;
|
|
20
|
+
readonly grantedAt: number;
|
|
21
|
+
readonly expiresAt: number;
|
|
22
|
+
}
|
|
23
|
+
export type StageResult = {
|
|
24
|
+
readonly ok: true;
|
|
25
|
+
readonly sha256: string;
|
|
26
|
+
readonly size: number;
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly expiresAt: number;
|
|
29
|
+
} | {
|
|
30
|
+
readonly ok: false;
|
|
31
|
+
readonly code: 'bad-request' | 'too-large' | 'full';
|
|
32
|
+
readonly error: string;
|
|
33
|
+
};
|
|
34
|
+
/** A file name that can only land inside the inbox: no path, no `..`, no control characters, bounded. */
|
|
35
|
+
export declare function sanitizeBlobName(name: string): string;
|
|
36
|
+
/** The one-line reference a session message carries (design §3.1). */
|
|
37
|
+
export declare function formatFileRef(ref: {
|
|
38
|
+
sha256: string;
|
|
39
|
+
size: number;
|
|
40
|
+
name: string;
|
|
41
|
+
from: string;
|
|
42
|
+
}): string;
|
|
43
|
+
/** Parse a reference line (anywhere in a message); undefined when it is not a well-formed v1 reference. */
|
|
44
|
+
export declare function parseFileRef(text: string): {
|
|
45
|
+
sha256: string;
|
|
46
|
+
size: number;
|
|
47
|
+
name: string;
|
|
48
|
+
from: string;
|
|
49
|
+
} | undefined;
|
|
50
|
+
export declare class BlobStore {
|
|
51
|
+
private readonly root;
|
|
52
|
+
private readonly now;
|
|
53
|
+
private grants;
|
|
54
|
+
/**
|
|
55
|
+
* @param root - the store's directory (`<home>/a2a`); '' = in-memory grants and no blob files (tests of the grant logic only).
|
|
56
|
+
* @param now - clock (tests).
|
|
57
|
+
*/
|
|
58
|
+
constructor(root: string, now?: () => number);
|
|
59
|
+
private get grantsFile();
|
|
60
|
+
private blobPath;
|
|
61
|
+
/** Stage bytes for `to`; a repeat of the same (sha256, to) only extends the grant. */
|
|
62
|
+
stage(bytes: Uint8Array, meta: {
|
|
63
|
+
name: string;
|
|
64
|
+
to: string;
|
|
65
|
+
by: string;
|
|
66
|
+
}): StageResult;
|
|
67
|
+
/**
|
|
68
|
+
* The live grant that lets one of `callerTeams` pull `sha256`, if any. `callerTeams` are the
|
|
69
|
+
* teams the WIRE FACE proved for the caller (OriginClaim + membership) — never self-described.
|
|
70
|
+
*/
|
|
71
|
+
grantFor(sha256: string, callerTeams: readonly string[]): BlobGrant | undefined;
|
|
72
|
+
/** The bytes of a granted blob (undefined when the file is gone or does not hash back). */
|
|
73
|
+
read(grant: BlobGrant): Uint8Array | undefined;
|
|
74
|
+
/** Live grants (for the state face). */
|
|
75
|
+
list(): readonly BlobGrant[];
|
|
76
|
+
private hasBlob;
|
|
77
|
+
/** Blobs some live grant still names, with their sizes. */
|
|
78
|
+
private liveBlobs;
|
|
79
|
+
/** Drop expired grants and every blob file no live grant names. */
|
|
80
|
+
private sweep;
|
|
81
|
+
private persist;
|
|
82
|
+
private restore;
|
|
83
|
+
}
|
|
@@ -29,11 +29,42 @@ export interface CliMail {
|
|
|
29
29
|
readonly at: number;
|
|
30
30
|
readonly from: string;
|
|
31
31
|
readonly text: string;
|
|
32
|
+
/**
|
|
33
|
+
* gh#113: the entry's place in its handle's mailbox — 1, 2, 3, … in
|
|
34
|
+
* arrival order, never reused, kept across restarts. A reader that keeps
|
|
35
|
+
* the last seq it read sees exactly what is new, and any gap below
|
|
36
|
+
* `oldest_seq` is mail the cap pushed out before it was read.
|
|
37
|
+
*/
|
|
38
|
+
readonly seq: number;
|
|
39
|
+
/** gh#113: set when `text` was cut to MAILBOX_TEXT_CAP; `chars` is the original length. */
|
|
40
|
+
readonly truncated?: true;
|
|
41
|
+
readonly chars?: number;
|
|
32
42
|
}
|
|
43
|
+
/** gh#113: one mailbox read — the rows plus what a reader needs to notice loss. */
|
|
44
|
+
export interface CliMailbox {
|
|
45
|
+
/** Newest first, as before gh#113. */
|
|
46
|
+
readonly mail: readonly CliMail[];
|
|
47
|
+
/** Changes when the store starts empty (no snapshot, or a corrupt one): seq restarted at 1. */
|
|
48
|
+
readonly epoch: string;
|
|
49
|
+
/** The seq the next delivery will get; `next_seq - 1` is the newest ever written. */
|
|
50
|
+
readonly next_seq: number;
|
|
51
|
+
/** The oldest seq still held, or `next_seq` when the mailbox is empty. */
|
|
52
|
+
readonly oldest_seq: number;
|
|
53
|
+
/** Entries the cap pushed out for this handle, all time. */
|
|
54
|
+
readonly dropped: number;
|
|
55
|
+
}
|
|
56
|
+
export declare const MAILBOX_CAP = 64;
|
|
57
|
+
export declare const MAILBOX_TEXT_CAP = 4000;
|
|
33
58
|
export declare class CliDepositStore {
|
|
34
59
|
private readonly path;
|
|
35
60
|
private deposits;
|
|
36
61
|
private mailbox;
|
|
62
|
+
private nextSeq;
|
|
63
|
+
private dropped;
|
|
64
|
+
private truncated;
|
|
65
|
+
private epoch;
|
|
66
|
+
/** gh#113 review: true while the last write failed — the epoch on disk no longer matches memory. */
|
|
67
|
+
private unpersisted;
|
|
37
68
|
private now;
|
|
38
69
|
constructor(path: string, options?: {
|
|
39
70
|
now?: () => number;
|
|
@@ -72,6 +103,13 @@ export declare class CliDepositStore {
|
|
|
72
103
|
}>;
|
|
73
104
|
mail(handle: string, from: string, text: string): void;
|
|
74
105
|
readMail(handle: string): readonly CliMail[];
|
|
106
|
+
/** gh#113: the mailbox with its seq bounds and loss counter; `afterSeq` keeps only newer rows. */
|
|
107
|
+
readMailbox(handle: string, afterSeq?: number): CliMailbox;
|
|
108
|
+
/** gh#113: fleet-wide loss counters for the state face (the team verifier reads them). */
|
|
109
|
+
mailStats(): {
|
|
110
|
+
dropped: number;
|
|
111
|
+
truncated: number;
|
|
112
|
+
};
|
|
75
113
|
private sweep;
|
|
76
114
|
/** Mark one row expired (tombstone) and persist. */
|
|
77
115
|
private markExpired;
|
|
@@ -15,6 +15,7 @@ import type { LayoutStore } from '../layout-store.ts';
|
|
|
15
15
|
import type { PeerStore } from '../peer-store.ts';
|
|
16
16
|
import { type TaskLedger } from '../task-ledger.ts';
|
|
17
17
|
import type { TeamMembershipStore } from '../team-store.ts';
|
|
18
|
+
import type { OriginClaimTarget } from '../origin-claim.ts';
|
|
18
19
|
/** Remote-team rows cached for the state face (see refreshRemoteRows). */
|
|
19
20
|
export type RemoteRowsCache = {
|
|
20
21
|
at: number;
|
|
@@ -25,11 +26,12 @@ export type RemoteRowsCache = {
|
|
|
25
26
|
via?: string;
|
|
26
27
|
workspace?: string;
|
|
27
28
|
legacy?: boolean;
|
|
29
|
+
unreachable?: boolean;
|
|
28
30
|
teams?: readonly string[];
|
|
29
31
|
}[];
|
|
30
32
|
} | undefined;
|
|
31
33
|
/** Everything the admin faces used to capture from `apply()`. */
|
|
32
|
-
export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim' | 'callerLinkedToThisHost' | 'cachedCardFetch'> {
|
|
34
|
+
export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim' | 'callerLinkedToThisHost' | 'cachedCardFetch' | 'peerFetch'> {
|
|
33
35
|
readonly ctx: Context;
|
|
34
36
|
readonly config: Config;
|
|
35
37
|
readonly logger: ReturnType<Context['logger']>;
|
|
@@ -51,7 +53,7 @@ export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim
|
|
|
51
53
|
link: 'linked' | 'stranger';
|
|
52
54
|
verified: boolean;
|
|
53
55
|
};
|
|
54
|
-
readonly originClaimHeaders: () => Record<string, string>;
|
|
56
|
+
readonly originClaimHeaders: (target: OriginClaimTarget) => Record<string, string>;
|
|
55
57
|
readonly refreshRemoteRows: () => void;
|
|
56
58
|
readonly joinedSessions: JoinedSessions;
|
|
57
59
|
readonly exposureStore: ExposureStore;
|
|
@@ -61,6 +63,8 @@ export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim
|
|
|
61
63
|
readonly canvasStore: CanvasStore;
|
|
62
64
|
readonly layoutStore: LayoutStore;
|
|
63
65
|
readonly taskLedger: TaskLedger;
|
|
66
|
+
/** #114 S6: observe (lazily) and return the /state `authorization` block. */
|
|
67
|
+
readonly authorizationView: () => unknown;
|
|
64
68
|
readonly idempotencyStore: IdempotencyStore;
|
|
65
69
|
readonly inFlightRoutes: Map<number, InFlightRoute>;
|
|
66
70
|
readonly recentActivity: RouteActivityEntry[];
|
|
@@ -108,6 +112,12 @@ export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim
|
|
|
108
112
|
readonly id8: (id: string) => string;
|
|
109
113
|
readonly sessionLabelOf: (agent: Agent) => string;
|
|
110
114
|
readonly sessionTeamOf: (agent: Agent) => string;
|
|
115
|
+
/** gh#131: the `<zone>/<id8>` handle a canvas may hold for this local session, if it reads as this session. */
|
|
116
|
+
readonly ownCanvasHandleOf: (id: string) => string | undefined;
|
|
117
|
+
/** gh#131: the local session a remote-shaped member ref reads as, if unambiguous. */
|
|
118
|
+
readonly localSessionOfHandle: (ref: string) => string | undefined;
|
|
119
|
+
/** gh#152: the session's canvas teams read through the local lens — a handle-stored membership of this session counts. */
|
|
120
|
+
readonly canvasTeamsOfSession: (id: string) => string[];
|
|
111
121
|
readonly nodeMetadataOf: (agent: Agent) => {
|
|
112
122
|
name: string;
|
|
113
123
|
description: string;
|
|
@@ -120,6 +130,8 @@ export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim
|
|
|
120
130
|
readonly cardCache: Map<string, CardCacheEntry>;
|
|
121
131
|
readonly remoteRowsCache: RemoteRowsCache;
|
|
122
132
|
readonly legacyInboundCount: number;
|
|
133
|
+
readonly unboundInboundCount: number;
|
|
134
|
+
readonly boundMissInboundCount: number;
|
|
123
135
|
readonly ownCardUrl: string;
|
|
124
136
|
ownerAllowlist: string[];
|
|
125
137
|
ownerTeamScopeInfo: boolean;
|
|
@@ -31,6 +31,7 @@ import type { A2aPeerCard } from '../types.ts';
|
|
|
31
31
|
import type { CanvasStore } from '../canvas-store.ts';
|
|
32
32
|
import type { PeerStore } from '../peer-store.ts';
|
|
33
33
|
import type { CardCacheEntry } from '../runtime.ts';
|
|
34
|
+
import type { OriginClaimTarget } from '../origin-claim.ts';
|
|
34
35
|
/** Coalesce a burst of store writes (a drag that adds three members) into one ping. */
|
|
35
36
|
export declare const CANVAS_NOTIFY_DEBOUNCE_MS = 400;
|
|
36
37
|
/** A peer's pings refresh its card at most this often. */
|
|
@@ -42,7 +43,7 @@ export interface CanvasNotifyDeps {
|
|
|
42
43
|
readonly peerStore: PeerStore;
|
|
43
44
|
readonly canvasStore: CanvasStore;
|
|
44
45
|
readonly cardCache: Map<string, CardCacheEntry>;
|
|
45
|
-
readonly originClaimHeaders: () => Record<string, string>;
|
|
46
|
+
readonly originClaimHeaders: (target: OriginClaimTarget) => Record<string, string>;
|
|
46
47
|
readonly verifyOriginClaim: (req: IncomingMessage) => Promise<{
|
|
47
48
|
ok: true;
|
|
48
49
|
caller: string;
|
|
@@ -54,6 +55,8 @@ export interface CanvasNotifyDeps {
|
|
|
54
55
|
}>;
|
|
55
56
|
readonly callerLinkedToThisHost: (caller: string, callerUrl: string, callerCard: A2aPeerCard | undefined) => boolean;
|
|
56
57
|
readonly cachedCardFetch: (url: string) => Promise<A2aPeerCard | undefined>;
|
|
58
|
+
/** gh#193: the host's guarded peer fetch (refuses while isolated). */
|
|
59
|
+
readonly peerFetch: typeof globalThis.fetch;
|
|
57
60
|
}
|
|
58
61
|
/**
|
|
59
62
|
* Re-read one peer's card now. Each pass pre-stales the entry (the literal
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #91 file channel, slice F1b (docs/design/file-channel.md §3.2, §3.4, §5): the two HTTP faces
|
|
3
|
+
* over the sender host's {@link BlobStore}.
|
|
4
|
+
*
|
|
5
|
+
* - `GET /a2a/blob?sha256=<hex>&caller_session=<label>` — the PULL face. Admission is the same
|
|
6
|
+
* reading the delivery face gives `已验证来源`: an OriginClaim that verifies, and for a host the
|
|
7
|
+
* audience-bound (v2) form signed from a ROOT card URL whose zone covers `caller_session`; a
|
|
8
|
+
* deposited CLI identity proves its own handle. The caller must then match a live grant's `to`:
|
|
9
|
+
* the caller's own label, the signer host itself or one of its canvas teams, or a canvas team of
|
|
10
|
+
* THIS host the caller itself is a member of ({@link grantAdmits}).
|
|
11
|
+
* A refusal never says whether the blob exists. Pulls are rate-limited per proven signer.
|
|
12
|
+
* - `POST /__dsh_a2a/blob?to=<team>&name=<file>` — the control-gated STAGE face (CLI `file send`,
|
|
13
|
+
* design §3.4): raw bytes in, a grant out. No peer can write into the store.
|
|
14
|
+
* @module @nelsonlongxiang/dsh-open-a2a-net/faces/files
|
|
15
|
+
*/
|
|
16
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
17
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
18
|
+
import type WebServer from '@deepseek-ai/dsh-host-webserver';
|
|
19
|
+
import type { Config } from '../index.ts';
|
|
20
|
+
import { type BlobStore } from '../blob-store.ts';
|
|
21
|
+
import type { CanvasStore } from '../canvas-store.ts';
|
|
22
|
+
import type { OriginClaimResult } from './wire.ts';
|
|
23
|
+
/** Pulls per proven signer (host zone or CLI handle) in a sliding minute (design §8; the FloodGuard figure). */
|
|
24
|
+
export declare const BLOB_PULLS_PER_MINUTE = 16;
|
|
25
|
+
export interface FileFaceDeps {
|
|
26
|
+
readonly ctx: Context;
|
|
27
|
+
readonly config: Pick<Config, 'apiKey' | 'team'>;
|
|
28
|
+
readonly blobStore: BlobStore;
|
|
29
|
+
readonly canvasStore: Pick<CanvasStore, 'membersOf'>;
|
|
30
|
+
readonly verifyOriginClaim: (req: IncomingMessage, options?: {
|
|
31
|
+
readonly cli?: boolean;
|
|
32
|
+
}) => Promise<OriginClaimResult>;
|
|
33
|
+
readonly secretEqual: (a: string, b: string) => boolean;
|
|
34
|
+
readonly controlRoute: (handler: (req: IncomingMessage, res: ServerResponse) => void) => (req: IncomingMessage, res: ServerResponse) => void;
|
|
35
|
+
readonly recordActivity: (dir: 'in' | 'out', team: string, peer: string, ok: boolean) => void;
|
|
36
|
+
readonly now?: () => number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Whether a grant's target lets this proven caller pull (design §3.2). For a HOST signer: the
|
|
40
|
+
* caller's own label; the signer host itself (a grant to the whole zone); one of the signer host's
|
|
41
|
+
* canvas teams (`<signer>/canvas/<name>` — that host answers for its own membership); or a canvas
|
|
42
|
+
* team of THIS host (`<zone>/canvas/<name>`; another host's same-named team is a different team) of
|
|
43
|
+
* which the caller ITSELF is a member. A grant to one session is not another session's, even on the
|
|
44
|
+
* same host (#91 F2: the honest host's tool names the pulling session, so a mistake cannot cross
|
|
45
|
+
* sessions). A CLI handle is an identity, never a zone (review of PR #208 R1): only its own grant.
|
|
46
|
+
* `caller` is already proven by `signer`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function grantAdmits(to: string, caller: string, signer: string, zone: string, localCanvasMembers: (name: string) => readonly string[], cli?: boolean): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Register the pull face and the stage face on the shared web server.
|
|
51
|
+
* @param d - the captures listed on {@link FileFaceDeps}.
|
|
52
|
+
*/
|
|
53
|
+
export declare function registerFileFaces(webServer: WebServer, d: FileFaceDeps): void;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `/__dsh_a2a/nodes` face (docs/design/node-identity.md, slice N1).
|
|
3
|
+
*
|
|
4
|
+
* - GET rides the ordinary control trust (loopback or apiKey): the roster,
|
|
5
|
+
* and with `?name=` one node plus its version numbers and current layers.
|
|
6
|
+
* - POST is an IDENTITY write (create / update / archive / write-core /
|
|
7
|
+
* write-mutable / rollback, bind / unbind a session — N2+N3, and track /
|
|
8
|
+
* untrack a task pointer — N6, and approve / reject a queued remote
|
|
9
|
+
* self-update — N4). §8-2 (owner ruling 2026-11-02): it requires
|
|
10
|
+
* the host's apiKey in `X-API-Key` even on loopback — a host with no
|
|
11
|
+
* apiKey refuses identity writes outright. No model tool reaches it.
|
|
12
|
+
* Same-host shell access can still edit the files; the design says so
|
|
13
|
+
* (§7) instead of pretending otherwise.
|
|
14
|
+
* @module src/faces/nodes
|
|
15
|
+
*/
|
|
16
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
17
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
18
|
+
import type WebServer from '@deepseek-ai/dsh-host-webserver';
|
|
19
|
+
import type { NodeStore } from '../node-store.ts';
|
|
20
|
+
import type { NodeBinder, NodeBindings } from '../node-bind.ts';
|
|
21
|
+
import type { NodeTasks } from '../node-tasks.ts';
|
|
22
|
+
import type { NodeReviewQueue } from '../node-self.ts';
|
|
23
|
+
/** Identity bodies carry layers of up to 3000 CJK characters; the 10 KiB control default is too small. */
|
|
24
|
+
export declare const NODE_BODY_MAX_BYTES = 32000;
|
|
25
|
+
export interface NodeFaceDeps {
|
|
26
|
+
readonly ctx: Context;
|
|
27
|
+
readonly logger: {
|
|
28
|
+
warn: (format: string, ...args: unknown[]) => void;
|
|
29
|
+
};
|
|
30
|
+
readonly nodeStore: NodeStore;
|
|
31
|
+
readonly bindings: NodeBindings;
|
|
32
|
+
readonly binder: NodeBinder;
|
|
33
|
+
readonly tasks: NodeTasks;
|
|
34
|
+
readonly reviews: NodeReviewQueue;
|
|
35
|
+
readonly apiKey: () => string;
|
|
36
|
+
readonly secretEqual: (a: string, b: string) => boolean;
|
|
37
|
+
readonly controlRoute: (handler: (req: IncomingMessage, res: ServerResponse) => void) => (req: IncomingMessage, res: ServerResponse) => void;
|
|
38
|
+
readonly readJsonBody: (req: IncomingMessage, res: ServerResponse, use: (body: {
|
|
39
|
+
readonly id?: unknown;
|
|
40
|
+
readonly name?: unknown;
|
|
41
|
+
readonly action?: unknown;
|
|
42
|
+
}) => void, maxBytes?: number) => void;
|
|
43
|
+
}
|
|
44
|
+
/** §8-2: identity writes need the configured apiKey in the header — loopback is not enough, and no key means no identity writes. */
|
|
45
|
+
export declare function identityVerdict(apiKey: string, presented: unknown, secretEqual: (a: string, b: string) => boolean): {
|
|
46
|
+
ok: true;
|
|
47
|
+
} | {
|
|
48
|
+
ok: false;
|
|
49
|
+
status: 401 | 403;
|
|
50
|
+
error: string;
|
|
51
|
+
};
|
|
52
|
+
/** One POST body → status + payload. Pure: the route below only does I/O and the identity gate. */
|
|
53
|
+
export declare function nodeAction(store: NodeStore, binder: NodeBinder, tasks: NodeTasks, reviews: NodeReviewQueue, raw: unknown): {
|
|
54
|
+
status: number;
|
|
55
|
+
payload: Record<string, unknown>;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* GET view: the roster with the bindings (and what each live session froze at mount), or one node
|
|
59
|
+
* with its version numbers and current layers. `current` only shows a version that passes the shape
|
|
60
|
+
* and sha checks (`null` otherwise) — the same reading a mount uses.
|
|
61
|
+
*/
|
|
62
|
+
export declare function nodeView(store: NodeStore, bindings: NodeBindings, binder: NodeBinder, tasks: NodeTasks, reviews: NodeReviewQueue, name: string | null, assembled?: ReadonlyMap<string, {
|
|
63
|
+
core: boolean;
|
|
64
|
+
mutable: boolean;
|
|
65
|
+
}>): {
|
|
66
|
+
status: number;
|
|
67
|
+
payload: Record<string, unknown>;
|
|
68
|
+
};
|
|
69
|
+
export declare function registerNodeFaces(webServer: WebServer, d: NodeFaceDeps): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gh#77 (src/index.ts line ratchet): the two session-log faces, moved verbatim out of apply() —
|
|
3
|
+
* the LOCAL transcript reader `/__dsh_a2a/session-log` and the REMOTE proxy
|
|
4
|
+
* `/__dsh_a2a/remote-session-log`. Behavior unchanged; apply() hands over the captures below.
|
|
5
|
+
* @module @nelsonlongxiang/dsh-open-a2a-net/faces/session-log
|
|
6
|
+
*/
|
|
7
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
8
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
9
|
+
import type WebServer from '@deepseek-ai/dsh-host-webserver';
|
|
10
|
+
import type { Config } from '../index.ts';
|
|
11
|
+
import type { PeerStore } from '../peer-store.ts';
|
|
12
|
+
import type { A2aPeerCard } from '../types.ts';
|
|
13
|
+
/** Everything the session-log faces capture from apply(). */
|
|
14
|
+
export interface SessionLogFaceDeps {
|
|
15
|
+
readonly ctx: Context;
|
|
16
|
+
readonly config: Pick<Config, 'team'>;
|
|
17
|
+
readonly controlRoute: (handler: (req: IncomingMessage, res: ServerResponse) => void) => (req: IncomingMessage, res: ServerResponse) => void;
|
|
18
|
+
readonly scanSessionLogList: () => Array<{
|
|
19
|
+
id: string;
|
|
20
|
+
mtimeMs: number;
|
|
21
|
+
sizeBytes: number;
|
|
22
|
+
}>;
|
|
23
|
+
readonly readSessionLogTail: (id: string, limit: number) => {
|
|
24
|
+
ok: true;
|
|
25
|
+
id: string;
|
|
26
|
+
messages: Array<{
|
|
27
|
+
role: string;
|
|
28
|
+
text: string;
|
|
29
|
+
time?: number;
|
|
30
|
+
}>;
|
|
31
|
+
} | {
|
|
32
|
+
ok: false;
|
|
33
|
+
error: string;
|
|
34
|
+
};
|
|
35
|
+
readonly peerStore: Pick<PeerStore, 'list'>;
|
|
36
|
+
readonly peerFetch: typeof globalThis.fetch;
|
|
37
|
+
readonly directoryPeerCandidates: (fetch: (url: string) => Promise<A2aPeerCard | undefined>, team: string, failures: string[]) => Promise<string[]>;
|
|
38
|
+
readonly memoizedCardFetch: () => (url: string) => Promise<A2aPeerCard | undefined>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Register the local transcript reader and the remote-log proxy on the shared web server.
|
|
42
|
+
* @param d - the captures listed on {@link SessionLogFaceDeps}.
|
|
43
|
+
*/
|
|
44
|
+
export declare function registerSessionLogFaces(webServer: WebServer, d: SessionLogFaceDeps): void;
|
|
@@ -20,7 +20,16 @@ import type { CliDepositStore } from '../cli-deposit.ts';
|
|
|
20
20
|
import type { IdempotencyStore } from '../idempotency-store.ts';
|
|
21
21
|
import type { JoinedSessions } from '../joined-store.ts';
|
|
22
22
|
import { type TaskLedger } from '../task-ledger.ts';
|
|
23
|
+
import { type Admission, type SettlementRefusal, type Settler } from '../task-auth.ts';
|
|
23
24
|
import type { Config } from '../index.ts';
|
|
25
|
+
/**
|
|
26
|
+
* #139 (design §4.4): add `settlement: {status:'refused', reason, task_id}`
|
|
27
|
+
* to whatever JSON object this response ends with. The delivery face has
|
|
28
|
+
* many exits (mailbox, no-wait, waiting, refusals); deferring the head until
|
|
29
|
+
* the body is known keeps one rule for all of them. A non-JSON or non-object
|
|
30
|
+
* body is sent unchanged.
|
|
31
|
+
*/
|
|
32
|
+
export declare function withSettlementField(res: ServerResponse, settlement: SettlementRefusal): void;
|
|
24
33
|
/** The cold-wake answer (mirrors index.ts's local ColdWake). */
|
|
25
34
|
export type ColdWake = {
|
|
26
35
|
readonly kind: 'flight';
|
|
@@ -98,6 +107,8 @@ export type OriginClaimResult = {
|
|
|
98
107
|
caller: string;
|
|
99
108
|
callerUrl: string;
|
|
100
109
|
card: A2aPeerCard;
|
|
110
|
+
bound: boolean;
|
|
111
|
+
cli?: true;
|
|
101
112
|
} | {
|
|
102
113
|
ok: false;
|
|
103
114
|
reason: string;
|
|
@@ -112,12 +123,22 @@ export interface WireDeps {
|
|
|
112
123
|
readonly sessionNodes: Map<string, Agent>;
|
|
113
124
|
readonly joinedSessions: JoinedSessions;
|
|
114
125
|
readonly idempotencyStore: IdempotencyStore;
|
|
115
|
-
readonly verifyOriginClaim: (req: IncomingMessage
|
|
126
|
+
readonly verifyOriginClaim: (req: IncomingMessage, options?: {
|
|
127
|
+
readonly cli?: boolean;
|
|
128
|
+
}) => Promise<OriginClaimResult>;
|
|
116
129
|
readonly callerLinkedToThisHost: (caller: string, callerUrl: string, callerCard: A2aPeerCard | undefined) => boolean;
|
|
130
|
+
/** This host's own card URL (read when a request lands; set once the web server settles). */
|
|
131
|
+
readonly ownCardUrl: string;
|
|
117
132
|
readonly recordActivity: (dir: 'in' | 'out', team: string, peer: string, ok: boolean) => void;
|
|
118
133
|
readonly bumpLegacyInbound: () => void;
|
|
119
134
|
readonly secretEqual: (a: string, b: string) => boolean;
|
|
120
135
|
readonly a2aCallerRefusal: (caller: string, targetTeam?: string) => string | undefined;
|
|
136
|
+
/** #114 S2: the same decision with the rule and basis that admitted the caller. */
|
|
137
|
+
readonly a2aCallerAdmission: (caller: string, targetTeam?: string) => Admission;
|
|
138
|
+
/** #114 S2: this host's allowlist version right now (design §2.3). */
|
|
139
|
+
readonly allowlistVersionNow: () => string;
|
|
140
|
+
/** #114 S6: record the version if it moved and re-judge affected tasks (observe only). */
|
|
141
|
+
readonly observeAuthorization: (cause: string) => void;
|
|
121
142
|
readonly scanSessionLogList: () => Array<{
|
|
122
143
|
id: string;
|
|
123
144
|
mtimeMs: number;
|
|
@@ -137,7 +158,8 @@ export interface WireDeps {
|
|
|
137
158
|
};
|
|
138
159
|
readonly taskLedger: TaskLedger;
|
|
139
160
|
readonly refuseIfFlooded: (caller: string, message: string, team: string, taskId: string, res: ServerResponse) => boolean;
|
|
140
|
-
|
|
161
|
+
/** Settles a receipt; returns the enforce refusal of the row its header names (#139), if any. */
|
|
162
|
+
readonly settleAndAnnounce: (message: string, settler?: Settler) => SettlementRefusal | undefined;
|
|
141
163
|
readonly touchWakeDemand: () => void;
|
|
142
164
|
readonly session: string;
|
|
143
165
|
readonly resolveAgentForTeam: (team: string) => Agent | undefined;
|
|
@@ -145,9 +167,16 @@ export interface WireDeps {
|
|
|
145
167
|
readonly canvasLiveAgent: (name: string | undefined, skipId?: string) => Agent | undefined;
|
|
146
168
|
readonly wakeColdTeam: (team: string, skipId?: string) => ColdWake;
|
|
147
169
|
readonly probeConsumption: (agent: Agent, taskId: string) => boolean;
|
|
170
|
+
/** A session's own node team (`<zone>/<id8>`), the handle a member is known by. */
|
|
171
|
+
readonly sessionTeamOf: (agent: Agent) => string;
|
|
172
|
+
/** gh#131: the local session one of this host's own `<zone>/<id8>` handles names, if exactly one. */
|
|
173
|
+
readonly localSessionOfHandle: (ref: string) => string | undefined;
|
|
148
174
|
readonly steerRelay: (agent: Agent, text: string, sender?: string) => void;
|
|
149
175
|
readonly fromClause: (from: string) => string;
|
|
150
|
-
readonly
|
|
176
|
+
readonly sanitizeFromClause: (from: string) => string;
|
|
177
|
+
readonly armReceiptAutosend: (target: Agent, taskId: string, callerTeam: string | undefined, deliveredText: string, steerFloor: number) => void;
|
|
178
|
+
/** #114 S5: the target's session-log length, read just before a steer. */
|
|
179
|
+
readonly eventCountOf: (agent: Agent) => number;
|
|
151
180
|
readonly receiptExpectationOf: (receiptTarget: string) => 'receivable' | 'process-label';
|
|
152
181
|
readonly armAsyncNudge: (agent: Agent, team: string, taskId: string, delayMs: number) => void;
|
|
153
182
|
readonly liveAgent: () => Agent | undefined;
|
|
@@ -159,9 +188,25 @@ export interface WireDeps {
|
|
|
159
188
|
readonly nativeTeamsPrepare: (team: string) => Promise<NativePrepared>;
|
|
160
189
|
readonly nativeTeamsRound: (prepared: Extract<NativePrepared, {
|
|
161
190
|
ok: true;
|
|
162
|
-
}>, team: string, caller: string, message: string, taskId: string | undefined) => Promise<NativeRoundOutcome>;
|
|
163
|
-
readonly routeIntoAgent: (team: string, message: string, caller: string, taskId?: string) => Promise<RouteOutcome>;
|
|
191
|
+
}>, team: string, caller: string, message: string, taskId: string | undefined, proofClause: string, external?: AbortSignal, proofHeader?: (team: string, taskId: string, from: string, proofClause: string) => string) => Promise<NativeRoundOutcome>;
|
|
192
|
+
readonly routeIntoAgent: (team: string, message: string, caller: string, taskId?: string, proofClause?: string, directHeader?: (from: string) => string) => Promise<RouteOutcome>;
|
|
164
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* #187: what a verified claim may vouch for at settlement. The signing key always (the card was
|
|
196
|
+
* fetched and its key verified); the ORIGIN only when the claim URL is that origin's root — a card
|
|
197
|
+
* fetched from a path under an origin proves the path's publisher, not the origin's host.
|
|
198
|
+
*/
|
|
199
|
+
export declare function settlerClaimFields(claim: {
|
|
200
|
+
ok: boolean;
|
|
201
|
+
cli?: true;
|
|
202
|
+
callerUrl?: string;
|
|
203
|
+
card?: {
|
|
204
|
+
publicKey: string;
|
|
205
|
+
};
|
|
206
|
+
}, originOf: (url: string) => string): {
|
|
207
|
+
claimOrigin?: string;
|
|
208
|
+
claimKey?: string;
|
|
209
|
+
};
|
|
165
210
|
/**
|
|
166
211
|
* Register the small wire faces on a settled web server.
|
|
167
212
|
* @param webServer - the settled host web server.
|