run402-mcp 3.0.0 → 3.2.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/core/dist/control-plane-session.d.ts +10 -7
- package/core/dist/control-plane-session.d.ts.map +1 -1
- package/core/dist/control-plane-session.js.map +1 -1
- package/core/dist/write-auth-session.d.ts +99 -0
- package/core/dist/write-auth-session.d.ts.map +1 -0
- package/core/dist/write-auth-session.js +174 -0
- package/core/dist/write-auth-session.js.map +1 -0
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +3 -1
- package/dist/sdk.js.map +1 -1
- package/package.json +1 -1
- package/sdk/core-dist/control-plane-session.d.ts +10 -7
- package/sdk/core-dist/write-auth-session.d.ts +99 -0
- package/sdk/core-dist/write-auth-session.js +174 -0
- package/sdk/dist/credentials.d.ts +28 -1
- package/sdk/dist/credentials.d.ts.map +1 -1
- package/sdk/dist/errors.d.ts +43 -1
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js +71 -0
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/index.d.ts +1 -1
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +1 -1
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/kernel.d.ts +3 -1
- package/sdk/dist/kernel.d.ts.map +1 -1
- package/sdk/dist/kernel.js +35 -4
- package/sdk/dist/kernel.js.map +1 -1
- package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.js +20 -4
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +13 -0
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.types.js.map +1 -1
- package/sdk/dist/namespaces/functions.d.ts +28 -15
- package/sdk/dist/namespaces/functions.d.ts.map +1 -1
- package/sdk/dist/namespaces/functions.js +64 -28
- package/sdk/dist/namespaces/functions.js.map +1 -1
- package/sdk/dist/namespaces/operator.d.ts +86 -3
- package/sdk/dist/namespaces/operator.d.ts.map +1 -1
- package/sdk/dist/namespaces/operator.js +55 -0
- package/sdk/dist/namespaces/operator.js.map +1 -1
- package/sdk/dist/namespaces/projects.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.js +11 -0
- package/sdk/dist/namespaces/projects.js.map +1 -1
- package/sdk/dist/namespaces/transfers.d.ts +4 -0
- package/sdk/dist/namespaces/transfers.d.ts.map +1 -1
- package/sdk/dist/namespaces/transfers.js +16 -1
- package/sdk/dist/namespaces/transfers.js.map +1 -1
- package/sdk/dist/node/credentials.d.ts +32 -6
- package/sdk/dist/node/credentials.d.ts.map +1 -1
- package/sdk/dist/node/credentials.js +57 -4
- package/sdk/dist/node/credentials.js.map +1 -1
- package/sdk/dist/node/index.d.ts +11 -1
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +3 -1
- package/sdk/dist/node/index.js.map +1 -1
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A cached **control-plane session** — the human principal's
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
2
|
+
* A cached **control-plane session** — the human principal's bearer, minted by
|
|
3
|
+
* the loopback-PKCE flow (`run402 operator login --loopback`). Distinct from the
|
|
4
|
+
* device-flow {@link OperatorSession} (read-only): this one carries `provenance`
|
|
5
|
+
* (`loopback_pkce`) and `amr`. It authorizes most control-plane operations, but
|
|
6
|
+
* since gateway v1.85/v1.87 it is NOT sufficient on its own for the high-stakes
|
|
7
|
+
* writes `provision` / `deploy` / secrets — those additionally require a
|
|
8
|
+
* passkey-fresh **operator approval** (`X-Run402-Write-Auth`, minted by
|
|
9
|
+
* `run402 operator approve`; see {@link WriteAuthApproval}). Cached at the BASE
|
|
10
|
+
* config dir (email/principal-scoped, shared across local named wallets), mode
|
|
11
|
+
* 0600 — the token is as sensitive as the allowance key.
|
|
9
12
|
*
|
|
10
13
|
* Stored shape vs the gateway payload: the gateway returns a relative
|
|
11
14
|
* `expires_in` (seconds); we persist the absolute `expires_at` (epoch ms) so a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-plane-session.d.ts","sourceRoot":"","sources":["../src/control-plane-session.ts"],"names":[],"mappings":"AAcA
|
|
1
|
+
{"version":3,"file":"control-plane-session.d.ts","sourceRoot":"","sources":["../src/control-plane-session.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,wBAAwB;IACvC,2BAA2B,EAAE,MAAM,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,WAAW,gCAAgC;IAC/C,2BAA2B,EAAE,MAAM,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAKnD;AAkBD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,wBAAwB,GAAG,IAAI,CA2CtF;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ3F;AAED,6FAA6F;AAC7F,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAO5D;AAED,mFAAmF;AACnF,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,wBAAwB,EACjC,KAAK,GAAE,MAAmB,EAC1B,MAAM,SAAS,GACd,OAAO,CAET;AAED,+FAA+F;AAC/F,wBAAgB,2BAA2B,CACzC,IAAI,CAAC,EAAE,MAAM,EACb,KAAK,GAAE,MAAmB,GACzB,wBAAwB,GAAG,IAAI,CAIjC;AAED,yGAAyG;AACzG,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,gCAAgC,EACtC,KAAK,GAAE,MAAmB,GACzB,wBAAwB,CAS1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-plane-session.js","sourceRoot":"","sources":["../src/control-plane-session.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,SAAS,EACT,UAAU,EACV,SAAS,EACT,UAAU,EACV,QAAQ,EACR,MAAM,GACP,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"control-plane-session.js","sourceRoot":"","sources":["../src/control-plane-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache of **operator-approval** tokens — the passkey-fresh write-auth tokens a
|
|
3
|
+
* wallet-less human mints to provision/deploy (gateway v1.85/v1.87). Distinct
|
|
4
|
+
* from the control-plane session ({@link ControlPlaneSessionCache}) it pairs
|
|
5
|
+
* with: the gateway scopes each token to one `(action, target)`, so this is a
|
|
6
|
+
* **multi-entry** cache keyed by `(api_origin, control_plane_session_hash,
|
|
7
|
+
* action, target)`. An `org.project.create` approval for org Y and a
|
|
8
|
+
* `project.deploy` approval for project X coexist.
|
|
9
|
+
*
|
|
10
|
+
* Stored at the BASE config dir (principal-scoped), mode 0600 — as sensitive as
|
|
11
|
+
* the allowance key. The token dies with its control-plane session; the
|
|
12
|
+
* `control_plane_session_hash` binding lets the client drop a stale approval
|
|
13
|
+
* locally rather than replay it into a `WRITE_AUTH_BINDING_MISMATCH`.
|
|
14
|
+
*/
|
|
15
|
+
export interface WriteAuthApproval {
|
|
16
|
+
write_auth_token: string;
|
|
17
|
+
token_type: string;
|
|
18
|
+
header: string;
|
|
19
|
+
/** Gateway capability: `org.project.create` | `project.deploy` | `project.secret.write`. */
|
|
20
|
+
action: string;
|
|
21
|
+
org_id?: string;
|
|
22
|
+
project_id?: string;
|
|
23
|
+
/** Epoch ms when the approval expires (derived from the gateway-returned session). */
|
|
24
|
+
expires_at: number;
|
|
25
|
+
/** Short hash of the control-plane session this approval is bound to. */
|
|
26
|
+
control_plane_session_hash: string;
|
|
27
|
+
control_plane_principal_id: string;
|
|
28
|
+
/** API origin (e.g. `https://api.run402.com`) the token was minted against. */
|
|
29
|
+
api_origin: string;
|
|
30
|
+
amr?: string[];
|
|
31
|
+
minted_at: number;
|
|
32
|
+
}
|
|
33
|
+
/** The token payload from `POST /agent/v1/control-plane/write-auth/cli/token`. */
|
|
34
|
+
export interface WriteAuthTokenResponse {
|
|
35
|
+
write_auth_token: string;
|
|
36
|
+
token_type?: string;
|
|
37
|
+
header?: string;
|
|
38
|
+
/** The write-auth session; its expiry is the token's expiry. */
|
|
39
|
+
session?: {
|
|
40
|
+
expires_at?: string | number;
|
|
41
|
+
absolute_expires_at?: string | number;
|
|
42
|
+
amr?: string[];
|
|
43
|
+
[k: string]: unknown;
|
|
44
|
+
} | null;
|
|
45
|
+
[k: string]: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** A capability target — exactly one of these is set per approval. */
|
|
48
|
+
export interface WriteAuthTargetKey {
|
|
49
|
+
org_id?: string;
|
|
50
|
+
project_id?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Path to the approval cache: `{base}/write-auth-session.json`.
|
|
54
|
+
* `RUN402_WRITE_AUTH_SESSION_PATH` overrides for testing.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getWriteAuthSessionPath(): string;
|
|
57
|
+
/** Stable short hash binding an approval to a control-plane session token. */
|
|
58
|
+
export declare function hashControlPlaneSession(token: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Read all cached approvals. Returns `[]` for the "no cache" cases (absent,
|
|
61
|
+
* unreadable, unparseable). Throws when the file parses as JSON but the shape
|
|
62
|
+
* is wrong, so a corrupted cache surfaces a clear fix-it.
|
|
63
|
+
*/
|
|
64
|
+
export declare function readApprovals(path?: string): WriteAuthApproval[];
|
|
65
|
+
/**
|
|
66
|
+
* Persist an approval. Replaces any existing entry with the same
|
|
67
|
+
* `(api_origin, control_plane_session_hash, action, target)` key and leaves
|
|
68
|
+
* every other entry intact (multi-entry, non-thrashing). Atomic, mode 0600.
|
|
69
|
+
*/
|
|
70
|
+
export declare function saveApproval(approval: WriteAuthApproval, path?: string): void;
|
|
71
|
+
/** Delete the whole approval cache — local half of `operator logout`. Idempotent. */
|
|
72
|
+
export declare function clearApprovals(path?: string): void;
|
|
73
|
+
/** Whether an approval is past its usable life (with a small skew buffer). */
|
|
74
|
+
export declare function isApprovalExpired(approval: WriteAuthApproval, nowMs?: number, skewMs?: number): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Return the cached approval matching ALL of `(apiOrigin, cpSessionHash,
|
|
77
|
+
* capability, target)` and still live, or `null` if none matches or it is
|
|
78
|
+
* expired. This is the exact-match the gateway's target gate requires — a
|
|
79
|
+
* non-match (wrong action/target/origin/session) fails closed.
|
|
80
|
+
*/
|
|
81
|
+
export declare function loadLiveApproval(q: {
|
|
82
|
+
apiOrigin: string;
|
|
83
|
+
cpSessionHash: string;
|
|
84
|
+
capability: string;
|
|
85
|
+
target: WriteAuthTargetKey;
|
|
86
|
+
}, path?: string, nowMs?: number): WriteAuthApproval | null;
|
|
87
|
+
/**
|
|
88
|
+
* Build a cache entry from the gateway token response + the binding context
|
|
89
|
+
* (the cp-session it was minted under, the API origin, and the `(action,
|
|
90
|
+
* target)` it covers). Expiry is taken from the returned `session`.
|
|
91
|
+
*/
|
|
92
|
+
export declare function approvalFromTokenResponse(resp: WriteAuthTokenResponse, binding: {
|
|
93
|
+
action: string;
|
|
94
|
+
target: WriteAuthTargetKey;
|
|
95
|
+
apiOrigin: string;
|
|
96
|
+
controlPlaneSessionHash: string;
|
|
97
|
+
controlPlanePrincipalId: string;
|
|
98
|
+
}, nowMs?: number): WriteAuthApproval;
|
|
99
|
+
//# sourceMappingURL=write-auth-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-auth-session.d.ts","sourceRoot":"","sources":["../src/write-auth-session.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,0BAA0B,EAAE,MAAM,CAAC;IACnC,0BAA0B,EAAE,MAAM,CAAC;IACnC,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,kFAAkF;AAClF,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/H,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED,sEAAsE;AACtE,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAKhD;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAgCD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,iBAAiB,EAAE,CA4BhE;AAyBD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAI7E;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAOlD;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,GAAE,MAAmB,EAC1B,MAAM,SAAS,GACd,OAAO,CAET;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,kBAAkB,CAAC;CAC5B,EACD,IAAI,CAAC,EAAE,MAAM,EACb,KAAK,GAAE,MAAmB,GACzB,iBAAiB,GAAG,IAAI,CAa1B;AAgBD;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,sBAAsB,EAC5B,OAAO,EAAE;IACP,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,kBAAkB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB,EAAE,MAAM,CAAC;IAChC,uBAAuB,EAAE,MAAM,CAAC;CACjC,EACD,KAAK,GAAE,MAAmB,GACzB,iBAAiB,CAkBnB"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync, renameSync, statSync, rmSync, } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { randomBytes, createHash } from "node:crypto";
|
|
4
|
+
import { getConfigBaseDir } from "./config.js";
|
|
5
|
+
const DEFAULT_TTL_MS = 30 * 60 * 1000;
|
|
6
|
+
/**
|
|
7
|
+
* Path to the approval cache: `{base}/write-auth-session.json`.
|
|
8
|
+
* `RUN402_WRITE_AUTH_SESSION_PATH` overrides for testing.
|
|
9
|
+
*/
|
|
10
|
+
export function getWriteAuthSessionPath() {
|
|
11
|
+
return (process.env.RUN402_WRITE_AUTH_SESSION_PATH ||
|
|
12
|
+
join(getConfigBaseDir(), "write-auth-session.json"));
|
|
13
|
+
}
|
|
14
|
+
/** Stable short hash binding an approval to a control-plane session token. */
|
|
15
|
+
export function hashControlPlaneSession(token) {
|
|
16
|
+
return createHash("sha256").update(token).digest("hex").slice(0, 32);
|
|
17
|
+
}
|
|
18
|
+
/** Tighten 0600 if group/other-readable, warning once. Best-effort, POSIX-only. */
|
|
19
|
+
function selfHealPermissions(p) {
|
|
20
|
+
if (process.platform === "win32")
|
|
21
|
+
return;
|
|
22
|
+
try {
|
|
23
|
+
const mode = statSync(p).mode & 0o777;
|
|
24
|
+
if ((mode & 0o077) !== 0) {
|
|
25
|
+
chmodSync(p, 0o600);
|
|
26
|
+
process.stderr.write(`warning: tightened permissions on ${p} from ${mode.toString(8)} to 600 (was readable by other users).\n`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Best-effort; never block a read on a chmod/stat failure.
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function isApproval(x) {
|
|
34
|
+
if (!x || typeof x !== "object")
|
|
35
|
+
return false;
|
|
36
|
+
const a = x;
|
|
37
|
+
return (typeof a.write_auth_token === "string" &&
|
|
38
|
+
a.write_auth_token.length > 0 &&
|
|
39
|
+
typeof a.action === "string" &&
|
|
40
|
+
typeof a.api_origin === "string" &&
|
|
41
|
+
typeof a.control_plane_session_hash === "string" &&
|
|
42
|
+
typeof a.expires_at === "number" &&
|
|
43
|
+
Number.isFinite(a.expires_at));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Read all cached approvals. Returns `[]` for the "no cache" cases (absent,
|
|
47
|
+
* unreadable, unparseable). Throws when the file parses as JSON but the shape
|
|
48
|
+
* is wrong, so a corrupted cache surfaces a clear fix-it.
|
|
49
|
+
*/
|
|
50
|
+
export function readApprovals(path) {
|
|
51
|
+
const p = path ?? getWriteAuthSessionPath();
|
|
52
|
+
if (!existsSync(p))
|
|
53
|
+
return [];
|
|
54
|
+
selfHealPermissions(p);
|
|
55
|
+
let raw;
|
|
56
|
+
try {
|
|
57
|
+
raw = readFileSync(p, "utf-8");
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
let parsed;
|
|
63
|
+
try {
|
|
64
|
+
parsed = JSON.parse(raw);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
70
|
+
throw new Error("write-auth-session.json must contain a JSON object. Delete it and re-run 'run402 operator approve' to recreate it.");
|
|
71
|
+
}
|
|
72
|
+
const approvals = parsed.approvals;
|
|
73
|
+
if (!Array.isArray(approvals)) {
|
|
74
|
+
throw new Error("write-auth-session.json missing an 'approvals' array. Delete it and re-run 'run402 operator approve'.");
|
|
75
|
+
}
|
|
76
|
+
return approvals.filter(isApproval);
|
|
77
|
+
}
|
|
78
|
+
function writeApprovals(approvals, path) {
|
|
79
|
+
const p = path ?? getWriteAuthSessionPath();
|
|
80
|
+
const dir = dirname(p);
|
|
81
|
+
mkdirSync(dir, { recursive: true });
|
|
82
|
+
const tmp = join(dir, `.write-auth-session.${randomBytes(4).toString("hex")}.tmp`);
|
|
83
|
+
writeFileSync(tmp, JSON.stringify({ approvals }, null, 2), { mode: 0o600 });
|
|
84
|
+
renameSync(tmp, p);
|
|
85
|
+
chmodSync(p, 0o600);
|
|
86
|
+
}
|
|
87
|
+
function sameTarget(a, b) {
|
|
88
|
+
return (a.org_id ?? null) === (b.org_id ?? null) && (a.project_id ?? null) === (b.project_id ?? null);
|
|
89
|
+
}
|
|
90
|
+
function sameKey(a, b) {
|
|
91
|
+
return (a.api_origin === b.api_origin &&
|
|
92
|
+
a.control_plane_session_hash === b.control_plane_session_hash &&
|
|
93
|
+
a.action === b.action &&
|
|
94
|
+
sameTarget(a, b));
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Persist an approval. Replaces any existing entry with the same
|
|
98
|
+
* `(api_origin, control_plane_session_hash, action, target)` key and leaves
|
|
99
|
+
* every other entry intact (multi-entry, non-thrashing). Atomic, mode 0600.
|
|
100
|
+
*/
|
|
101
|
+
export function saveApproval(approval, path) {
|
|
102
|
+
const existing = readApprovals(path).filter((a) => !sameKey(a, approval));
|
|
103
|
+
existing.push(approval);
|
|
104
|
+
writeApprovals(existing, path);
|
|
105
|
+
}
|
|
106
|
+
/** Delete the whole approval cache — local half of `operator logout`. Idempotent. */
|
|
107
|
+
export function clearApprovals(path) {
|
|
108
|
+
const p = path ?? getWriteAuthSessionPath();
|
|
109
|
+
try {
|
|
110
|
+
rmSync(p, { force: true });
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Best-effort: a failed unlink should never crash logout.
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** Whether an approval is past its usable life (with a small skew buffer). */
|
|
117
|
+
export function isApprovalExpired(approval, nowMs = Date.now(), skewMs = 10_000) {
|
|
118
|
+
return nowMs + skewMs >= approval.expires_at;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Return the cached approval matching ALL of `(apiOrigin, cpSessionHash,
|
|
122
|
+
* capability, target)` and still live, or `null` if none matches or it is
|
|
123
|
+
* expired. This is the exact-match the gateway's target gate requires — a
|
|
124
|
+
* non-match (wrong action/target/origin/session) fails closed.
|
|
125
|
+
*/
|
|
126
|
+
export function loadLiveApproval(q, path, nowMs = Date.now()) {
|
|
127
|
+
for (const a of readApprovals(path)) {
|
|
128
|
+
if (a.api_origin === q.apiOrigin &&
|
|
129
|
+
a.control_plane_session_hash === q.cpSessionHash &&
|
|
130
|
+
a.action === q.capability &&
|
|
131
|
+
sameTarget(a, q.target) &&
|
|
132
|
+
!isApprovalExpired(a, nowMs)) {
|
|
133
|
+
return a;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
/** Parse a gateway-returned session expiry (ISO string or epoch) to epoch ms. */
|
|
139
|
+
function sessionExpiryMs(session, nowMs) {
|
|
140
|
+
const raw = session?.expires_at ?? session?.absolute_expires_at;
|
|
141
|
+
if (typeof raw === "number" && Number.isFinite(raw))
|
|
142
|
+
return raw > 1e12 ? raw : raw * 1000;
|
|
143
|
+
if (typeof raw === "string") {
|
|
144
|
+
const ms = Date.parse(raw);
|
|
145
|
+
if (Number.isFinite(ms))
|
|
146
|
+
return ms;
|
|
147
|
+
}
|
|
148
|
+
return nowMs + DEFAULT_TTL_MS;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Build a cache entry from the gateway token response + the binding context
|
|
152
|
+
* (the cp-session it was minted under, the API origin, and the `(action,
|
|
153
|
+
* target)` it covers). Expiry is taken from the returned `session`.
|
|
154
|
+
*/
|
|
155
|
+
export function approvalFromTokenResponse(resp, binding, nowMs = Date.now()) {
|
|
156
|
+
const amr = Array.isArray(resp.session?.amr)
|
|
157
|
+
? resp.session.amr.filter((a) => typeof a === "string")
|
|
158
|
+
: undefined;
|
|
159
|
+
return {
|
|
160
|
+
write_auth_token: resp.write_auth_token,
|
|
161
|
+
token_type: typeof resp.token_type === "string" ? resp.token_type : "write_auth",
|
|
162
|
+
header: typeof resp.header === "string" ? resp.header : "X-Run402-Write-Auth",
|
|
163
|
+
action: binding.action,
|
|
164
|
+
...(binding.target.org_id ? { org_id: binding.target.org_id } : {}),
|
|
165
|
+
...(binding.target.project_id ? { project_id: binding.target.project_id } : {}),
|
|
166
|
+
expires_at: sessionExpiryMs(resp.session, nowMs),
|
|
167
|
+
control_plane_session_hash: binding.controlPlaneSessionHash,
|
|
168
|
+
control_plane_principal_id: binding.controlPlanePrincipalId,
|
|
169
|
+
api_origin: binding.apiOrigin,
|
|
170
|
+
...(amr ? { amr } : {}),
|
|
171
|
+
minted_at: nowMs,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=write-auth-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-auth-session.js","sourceRoot":"","sources":["../src/write-auth-session.ts"],"names":[],"mappings":"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"}
|
package/dist/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAIrF,wBAAgB,MAAM,IAAI,UAAU,
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAIrF,wBAAgB,MAAM,IAAI,UAAU,CAKnC;AAED,gDAAgD;AAChD,wBAAgB,SAAS,IAAI,IAAI,CAEhC"}
|
package/dist/sdk.js
CHANGED
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
import { run402 as createNodeSdk } from "../sdk/dist/node/index.js";
|
|
11
11
|
let cached = null;
|
|
12
12
|
export function getSdk() {
|
|
13
|
+
// surface: "mcp" keeps credential resolution wallet-only — an agent tool call
|
|
14
|
+
// never spends the human's cached operator approval (no ambient authority).
|
|
13
15
|
if (!cached)
|
|
14
|
-
cached = createNodeSdk();
|
|
16
|
+
cached = createNodeSdk({ surface: "mcp" });
|
|
15
17
|
return cached;
|
|
16
18
|
}
|
|
17
19
|
/** Reset the cached SDK instance. Test-only. */
|
package/dist/sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,IAAI,aAAa,EAAmB,MAAM,2BAA2B,CAAC;AAErF,IAAI,MAAM,GAAsB,IAAI,CAAC;AAErC,MAAM,UAAU,MAAM;IACpB,IAAI,CAAC,MAAM;QAAE,MAAM,GAAG,aAAa,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,IAAI,aAAa,EAAmB,MAAM,2BAA2B,CAAC;AAErF,IAAI,MAAM,GAAsB,IAAI,CAAC;AAErC,MAAM,UAAU,MAAM;IACpB,8EAA8E;IAC9E,4EAA4E;IAC5E,IAAI,CAAC,MAAM;QAAE,MAAM,GAAG,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "run402-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "MCP server for Run402 — AI-native Postgres databases with REST API, auth, storage, and row-level security. Pay with x402 USDC micropayments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A cached **control-plane session** — the human principal's
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
2
|
+
* A cached **control-plane session** — the human principal's bearer, minted by
|
|
3
|
+
* the loopback-PKCE flow (`run402 operator login --loopback`). Distinct from the
|
|
4
|
+
* device-flow {@link OperatorSession} (read-only): this one carries `provenance`
|
|
5
|
+
* (`loopback_pkce`) and `amr`. It authorizes most control-plane operations, but
|
|
6
|
+
* since gateway v1.85/v1.87 it is NOT sufficient on its own for the high-stakes
|
|
7
|
+
* writes `provision` / `deploy` / secrets — those additionally require a
|
|
8
|
+
* passkey-fresh **operator approval** (`X-Run402-Write-Auth`, minted by
|
|
9
|
+
* `run402 operator approve`; see {@link WriteAuthApproval}). Cached at the BASE
|
|
10
|
+
* config dir (email/principal-scoped, shared across local named wallets), mode
|
|
11
|
+
* 0600 — the token is as sensitive as the allowance key.
|
|
9
12
|
*
|
|
10
13
|
* Stored shape vs the gateway payload: the gateway returns a relative
|
|
11
14
|
* `expires_in` (seconds); we persist the absolute `expires_at` (epoch ms) so a
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache of **operator-approval** tokens — the passkey-fresh write-auth tokens a
|
|
3
|
+
* wallet-less human mints to provision/deploy (gateway v1.85/v1.87). Distinct
|
|
4
|
+
* from the control-plane session ({@link ControlPlaneSessionCache}) it pairs
|
|
5
|
+
* with: the gateway scopes each token to one `(action, target)`, so this is a
|
|
6
|
+
* **multi-entry** cache keyed by `(api_origin, control_plane_session_hash,
|
|
7
|
+
* action, target)`. An `org.project.create` approval for org Y and a
|
|
8
|
+
* `project.deploy` approval for project X coexist.
|
|
9
|
+
*
|
|
10
|
+
* Stored at the BASE config dir (principal-scoped), mode 0600 — as sensitive as
|
|
11
|
+
* the allowance key. The token dies with its control-plane session; the
|
|
12
|
+
* `control_plane_session_hash` binding lets the client drop a stale approval
|
|
13
|
+
* locally rather than replay it into a `WRITE_AUTH_BINDING_MISMATCH`.
|
|
14
|
+
*/
|
|
15
|
+
export interface WriteAuthApproval {
|
|
16
|
+
write_auth_token: string;
|
|
17
|
+
token_type: string;
|
|
18
|
+
header: string;
|
|
19
|
+
/** Gateway capability: `org.project.create` | `project.deploy` | `project.secret.write`. */
|
|
20
|
+
action: string;
|
|
21
|
+
org_id?: string;
|
|
22
|
+
project_id?: string;
|
|
23
|
+
/** Epoch ms when the approval expires (derived from the gateway-returned session). */
|
|
24
|
+
expires_at: number;
|
|
25
|
+
/** Short hash of the control-plane session this approval is bound to. */
|
|
26
|
+
control_plane_session_hash: string;
|
|
27
|
+
control_plane_principal_id: string;
|
|
28
|
+
/** API origin (e.g. `https://api.run402.com`) the token was minted against. */
|
|
29
|
+
api_origin: string;
|
|
30
|
+
amr?: string[];
|
|
31
|
+
minted_at: number;
|
|
32
|
+
}
|
|
33
|
+
/** The token payload from `POST /agent/v1/control-plane/write-auth/cli/token`. */
|
|
34
|
+
export interface WriteAuthTokenResponse {
|
|
35
|
+
write_auth_token: string;
|
|
36
|
+
token_type?: string;
|
|
37
|
+
header?: string;
|
|
38
|
+
/** The write-auth session; its expiry is the token's expiry. */
|
|
39
|
+
session?: {
|
|
40
|
+
expires_at?: string | number;
|
|
41
|
+
absolute_expires_at?: string | number;
|
|
42
|
+
amr?: string[];
|
|
43
|
+
[k: string]: unknown;
|
|
44
|
+
} | null;
|
|
45
|
+
[k: string]: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** A capability target — exactly one of these is set per approval. */
|
|
48
|
+
export interface WriteAuthTargetKey {
|
|
49
|
+
org_id?: string;
|
|
50
|
+
project_id?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Path to the approval cache: `{base}/write-auth-session.json`.
|
|
54
|
+
* `RUN402_WRITE_AUTH_SESSION_PATH` overrides for testing.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getWriteAuthSessionPath(): string;
|
|
57
|
+
/** Stable short hash binding an approval to a control-plane session token. */
|
|
58
|
+
export declare function hashControlPlaneSession(token: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Read all cached approvals. Returns `[]` for the "no cache" cases (absent,
|
|
61
|
+
* unreadable, unparseable). Throws when the file parses as JSON but the shape
|
|
62
|
+
* is wrong, so a corrupted cache surfaces a clear fix-it.
|
|
63
|
+
*/
|
|
64
|
+
export declare function readApprovals(path?: string): WriteAuthApproval[];
|
|
65
|
+
/**
|
|
66
|
+
* Persist an approval. Replaces any existing entry with the same
|
|
67
|
+
* `(api_origin, control_plane_session_hash, action, target)` key and leaves
|
|
68
|
+
* every other entry intact (multi-entry, non-thrashing). Atomic, mode 0600.
|
|
69
|
+
*/
|
|
70
|
+
export declare function saveApproval(approval: WriteAuthApproval, path?: string): void;
|
|
71
|
+
/** Delete the whole approval cache — local half of `operator logout`. Idempotent. */
|
|
72
|
+
export declare function clearApprovals(path?: string): void;
|
|
73
|
+
/** Whether an approval is past its usable life (with a small skew buffer). */
|
|
74
|
+
export declare function isApprovalExpired(approval: WriteAuthApproval, nowMs?: number, skewMs?: number): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Return the cached approval matching ALL of `(apiOrigin, cpSessionHash,
|
|
77
|
+
* capability, target)` and still live, or `null` if none matches or it is
|
|
78
|
+
* expired. This is the exact-match the gateway's target gate requires — a
|
|
79
|
+
* non-match (wrong action/target/origin/session) fails closed.
|
|
80
|
+
*/
|
|
81
|
+
export declare function loadLiveApproval(q: {
|
|
82
|
+
apiOrigin: string;
|
|
83
|
+
cpSessionHash: string;
|
|
84
|
+
capability: string;
|
|
85
|
+
target: WriteAuthTargetKey;
|
|
86
|
+
}, path?: string, nowMs?: number): WriteAuthApproval | null;
|
|
87
|
+
/**
|
|
88
|
+
* Build a cache entry from the gateway token response + the binding context
|
|
89
|
+
* (the cp-session it was minted under, the API origin, and the `(action,
|
|
90
|
+
* target)` it covers). Expiry is taken from the returned `session`.
|
|
91
|
+
*/
|
|
92
|
+
export declare function approvalFromTokenResponse(resp: WriteAuthTokenResponse, binding: {
|
|
93
|
+
action: string;
|
|
94
|
+
target: WriteAuthTargetKey;
|
|
95
|
+
apiOrigin: string;
|
|
96
|
+
controlPlaneSessionHash: string;
|
|
97
|
+
controlPlanePrincipalId: string;
|
|
98
|
+
}, nowMs?: number): WriteAuthApproval;
|
|
99
|
+
//# sourceMappingURL=write-auth-session.d.ts.map
|