@rubytech/create-maxy-code 0.1.437 → 0.1.438
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/package.json +1 -1
- package/payload/platform/lib/admin-access-password/__tests__/index.test.ts +31 -0
- package/payload/platform/lib/admin-access-password/dist/index.d.ts +8 -0
- package/payload/platform/lib/admin-access-password/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/admin-access-password/dist/index.js +5 -1
- package/payload/platform/lib/admin-access-password/dist/index.js.map +1 -1
- package/payload/platform/lib/admin-access-password/src/index.ts +14 -1
- package/payload/platform/lib/admins-write/__tests__/index.test.ts +27 -0
- package/payload/platform/lib/admins-write/dist/index.d.ts +8 -0
- package/payload/platform/lib/admins-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/admins-write/dist/index.js +5 -1
- package/payload/platform/lib/admins-write/dist/index.js.map +1 -1
- package/payload/platform/lib/admins-write/src/index.ts +14 -1
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +4 -2
- package/payload/platform/plugins/admin/mcp/dist/credential-identity.d.ts +23 -0
- package/payload/platform/plugins/admin/mcp/dist/credential-identity.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/credential-identity.js +35 -0
- package/payload/platform/plugins/admin/mcp/dist/credential-identity.js.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js +110 -57
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +22 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +62 -2
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
- package/payload/platform/plugins/docs/references/admin-identity-gate.md +40 -0
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/profile.md +1 -1
- package/payload/platform/scripts/remediate-glsmith-identity.sh +500 -0
- package/payload/platform/scripts/seed-neo4j.sh +77 -12
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +20 -4
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/identity-audit.d.ts +51 -0
- package/payload/platform/services/claude-session-manager/dist/identity-audit.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/identity-audit.js +103 -0
- package/payload/platform/services/claude-session-manager/dist/identity-audit.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/index.js +33 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.d.ts +25 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.js +42 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.d.ts +44 -0
- package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.js +127 -0
- package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.js.map +1 -0
- package/payload/server/{chunk-LMLVOZ6G.js → chunk-UGPQCVIW.js} +11 -38
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/server.js +15 -16
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import type { CreatedBy } from "../../../../../lib/graph-write/dist/index.js";
|
|
2
|
+
/** Task 1567 — the name-required invariant for every owner-creating seed path.
|
|
3
|
+
* A name is a placeholder (and so must be refused, never persisted) when, after
|
|
4
|
+
* trimming, it is empty or equal to the literal seed placeholder "Owner". A
|
|
5
|
+
* real name that merely contains the word — "Owner Jones" — is not a
|
|
6
|
+
* placeholder. This is the single predicate the sub-account seed, account_create
|
|
7
|
+
* and admin-add all route through, and the same condition the standing
|
|
8
|
+
* placeholder-owner audit detects on already-persisted nodes. */
|
|
9
|
+
export declare function isPlaceholderOwnerName(name: string): boolean;
|
|
2
10
|
export interface AccountSummary {
|
|
3
11
|
accountId: string;
|
|
4
12
|
role: string;
|
|
@@ -14,6 +22,20 @@ export declare function isHouseAccount(accountsDir: string, id: string): boolean
|
|
|
14
22
|
* (should not happen on a correctly-provisioned install — callers treat
|
|
15
23
|
* null as "no house configured yet" rather than throwing). */
|
|
16
24
|
export declare function findHouseAccount(accountsDir: string): AccountSummary | null;
|
|
25
|
+
export interface AdminAddClientRefusal {
|
|
26
|
+
/** stderr diagnostic line. */
|
|
27
|
+
logLine: string;
|
|
28
|
+
/** operator-facing refusal message (prefixed with the tool TAG by the caller). */
|
|
29
|
+
message: string;
|
|
30
|
+
}
|
|
31
|
+
/** Task 1568 — admin-add mints a per-account operator seat (users.json PIN,
|
|
32
|
+
* account.json admins[], graph AdminUser/Person). Since Task 999 admin access is
|
|
33
|
+
* install-wide: a house admin reaches every sub-account with no seat on it
|
|
34
|
+
* (canAccessAdmin never consults admins[]). On a client sub-account a seat
|
|
35
|
+
* therefore grants nothing and only fragments identity, so admin-add is refused
|
|
36
|
+
* there. The house account is unaffected: it is where operators legitimately
|
|
37
|
+
* hold PIN logins and admins[] rows. Returns null on the house (proceed). */
|
|
38
|
+
export declare function refuseClientAdminAdd(isHouse: boolean, accountId: string): AdminAddClientRefusal | null;
|
|
17
39
|
/** Task 1311 — reads the install-wide WhatsApp/Telegram channel-routing
|
|
18
40
|
* pointer off the house account's account.json. Returns null when absent
|
|
19
41
|
* (default: inbound routes to house, unchanged from pre-1311 behavior) or
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-lifecycle.d.ts","sourceRoot":"","sources":["../../src/tools/account-lifecycle.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"account-lifecycle.d.ts","sourceRoot":"","sources":["../../src/tools/account-lifecycle.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8CAA8C,CAAC;AAI9E;;;;;;kEAMkE;AAClE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG5D;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;oCAEoC;AACpC,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,EAAE,CAoBzE;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED;;+DAE+D;AAC/D,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAE3E;AAED,MAAM,WAAW,qBAAqB;IACpC,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;8EAM8E;AAC9E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAOtG;AAED;;;;;+DAK+D;AAC/D,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU7E;AAED;;;;0EAI0E;AAC1E,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,CAO7F;AAED;;;;mEAImE;AACnE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAanE;AAED;;;;sEAIsE;AACtE,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAKlG;AAED;;;;;;;;;;;;4EAY4E;AAC5E,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB9F;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,YAAY,GAAG,YAAY,GAAG,eAAe,CAAA;CAAE,CAAC;AAEzE;;;;;;;;;qBASqB;AACrB,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,CAcjH;AAED;;iFAEiF;AACjF,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAO3C;AAED;;;yBAGyB;AACzB,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,MAAM,CAoBT;AAED;iEACiE;AACjE,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAClH;AAED;;;;;;;0BAO0B;AAC1B,eAAO,MAAM,WAAW,EAAE,SAAoD,CAAC;AAE/E;;;;;;;;;;;;;;;;;;+BAkB+B;AAC/B,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,cAAc,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,CA0D7D;AAED;;mEAEmE;AACnE,eAAO,MAAM,yBAAyB,2DAA2D,CAAC;AAClG,eAAO,MAAM,oBAAoB,sDAAsD,CAAC"}
|
|
@@ -7,6 +7,17 @@ import { execFileSync } from "node:child_process";
|
|
|
7
7
|
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { join, resolve } from "node:path";
|
|
9
9
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10
|
+
/** Task 1567 — the name-required invariant for every owner-creating seed path.
|
|
11
|
+
* A name is a placeholder (and so must be refused, never persisted) when, after
|
|
12
|
+
* trimming, it is empty or equal to the literal seed placeholder "Owner". A
|
|
13
|
+
* real name that merely contains the word — "Owner Jones" — is not a
|
|
14
|
+
* placeholder. This is the single predicate the sub-account seed, account_create
|
|
15
|
+
* and admin-add all route through, and the same condition the standing
|
|
16
|
+
* placeholder-owner audit detects on already-persisted nodes. */
|
|
17
|
+
export function isPlaceholderOwnerName(name) {
|
|
18
|
+
const trimmed = name.trim();
|
|
19
|
+
return trimmed === "" || trimmed === "Owner";
|
|
20
|
+
}
|
|
10
21
|
/** Enumerate the registry: every UUID dir with a parseable account.json, with
|
|
11
22
|
* its role. An unparseable account.json is excluded (corruption discipline,
|
|
12
23
|
* mirrors account-enumeration). */
|
|
@@ -44,6 +55,21 @@ export function isHouseAccount(accountsDir, id) {
|
|
|
44
55
|
export function findHouseAccount(accountsDir) {
|
|
45
56
|
return listAccountsFromDir(accountsDir).find((a) => a.isHouse) ?? null;
|
|
46
57
|
}
|
|
58
|
+
/** Task 1568 — admin-add mints a per-account operator seat (users.json PIN,
|
|
59
|
+
* account.json admins[], graph AdminUser/Person). Since Task 999 admin access is
|
|
60
|
+
* install-wide: a house admin reaches every sub-account with no seat on it
|
|
61
|
+
* (canAccessAdmin never consults admins[]). On a client sub-account a seat
|
|
62
|
+
* therefore grants nothing and only fragments identity, so admin-add is refused
|
|
63
|
+
* there. The house account is unaffected: it is where operators legitimately
|
|
64
|
+
* hold PIN logins and admins[] rows. Returns null on the house (proceed). */
|
|
65
|
+
export function refuseClientAdminAdd(isHouse, accountId) {
|
|
66
|
+
if (isHouse)
|
|
67
|
+
return null;
|
|
68
|
+
return {
|
|
69
|
+
logLine: `[admin-add] op=refused-on-client reason=install-wide-access-no-seat account=${accountId.slice(0, 8)}`,
|
|
70
|
+
message: "Admin access is install-wide. A house admin already reaches this sub-account with no seat on it, so no per-sub-account admin is created. The sub-account's one identity, its business owner, is set when the account is created.",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
47
73
|
/** Task 1311 — reads the install-wide WhatsApp/Telegram channel-routing
|
|
48
74
|
* pointer off the house account's account.json. Returns null when absent
|
|
49
75
|
* (default: inbound routes to house, unchanged from pre-1311 behavior) or
|
|
@@ -235,6 +261,26 @@ export const SEED_ORIGIN = { agent: "system", source: "installer" };
|
|
|
235
261
|
* verified post-condition. */
|
|
236
262
|
export async function seedAccountGraphRoot(args) {
|
|
237
263
|
const { session, accountId, ownerUserId, ownerName, createdAt } = args;
|
|
264
|
+
// Task 1567 — the business owner's name is a hard precondition of the seed.
|
|
265
|
+
// Refuse before any write so a nameless create leaves no partial rootless
|
|
266
|
+
// scaffold behind (no LocalBusiness, no AdminUser, no Person). Mirrors the
|
|
267
|
+
// empty-fullName throw writeAdminUserAndPerson already enforces; here it is
|
|
268
|
+
// reached at the seed point, and it additionally refuses the "Owner"
|
|
269
|
+
// placeholder the old default persisted.
|
|
270
|
+
const trimmedName = ownerName.trim();
|
|
271
|
+
if (isPlaceholderOwnerName(ownerName)) {
|
|
272
|
+
throw new Error(`seedAccountGraphRoot: a real business-owner name is required (got ${JSON.stringify(ownerName)})`);
|
|
273
|
+
}
|
|
274
|
+
// Split on first whitespace, same rule as writeAdminUserAndPerson: head →
|
|
275
|
+
// givenName, tail trimmed → familyName (null if empty). Single-token names
|
|
276
|
+
// land as givenName only.
|
|
277
|
+
const firstSpace = trimmedName.search(/\s/);
|
|
278
|
+
const givenName = firstSpace === -1 ? trimmedName : trimmedName.slice(0, firstSpace).trim();
|
|
279
|
+
const familyName = firstSpace === -1 ? null : trimmedName.slice(firstSpace + 1).trim() || null;
|
|
280
|
+
// The owner :Person carries the same admin-personal shape the house owner's
|
|
281
|
+
// Person gets (writeAdminUserAndPerson). embedding is null here — a fresh
|
|
282
|
+
// sub-account is unpopulated, and the standing reindex embeds it; the seed
|
|
283
|
+
// must not depend on an embedder to keep it unit-testable and boot-safe.
|
|
238
284
|
const res = await session.run(`MERGE (lb:LocalBusiness {accountId: $accountId})
|
|
239
285
|
ON CREATE SET lb.createdBySource = 'installer',
|
|
240
286
|
lb.createdByAgent = 'system',
|
|
@@ -242,14 +288,28 @@ export async function seedAccountGraphRoot(args) {
|
|
|
242
288
|
MERGE (au:AdminUser {userId: $ownerUserId})
|
|
243
289
|
ON CREATE SET au.accountId = $accountId,
|
|
244
290
|
au.role = 'owner',
|
|
245
|
-
au.name = $ownerName,
|
|
246
291
|
au.createdAt = $createdAt
|
|
247
292
|
ON MATCH SET au.accountId = COALESCE(au.accountId, $accountId)
|
|
248
293
|
MERGE (au)-[r:ADMIN_OF]->(lb)
|
|
249
294
|
ON CREATE SET r.role = 'owner', r.grantedAt = $createdAt
|
|
295
|
+
// Task 1567 — the owner Person, created in the same statement so the name
|
|
296
|
+
// is never a field backfilled later. MERGE-keyed on (accountId, ownerUserId)
|
|
297
|
+
// so the whole seed stays idempotent to match the LocalBusiness/AdminUser
|
|
298
|
+
// MERGEs above it — a plain CREATE would duplicate the Person on any replay.
|
|
299
|
+
MERGE (au)-[:OWNS]->(owner:Person {accountId: $accountId, userId: $ownerUserId})
|
|
300
|
+
ON CREATE SET owner.givenName = $givenName,
|
|
301
|
+
owner.familyName = $familyName,
|
|
302
|
+
owner.role = 'admin-personal',
|
|
303
|
+
owner.scope = 'admin',
|
|
304
|
+
owner.embedding = null,
|
|
305
|
+
owner.createdAt = $createdAt
|
|
250
306
|
WITH lb.accountId AS acct
|
|
251
307
|
RETURN COUNT { MATCH (b:LocalBusiness {accountId: acct}) } > 0 AS hasBusiness,
|
|
252
|
-
COUNT { MATCH (a:AdminUser {accountId: acct}) } > 0 AS hasAdmin`,
|
|
308
|
+
COUNT { MATCH (a:AdminUser {accountId: acct}) } > 0 AS hasAdmin`,
|
|
309
|
+
// Task 1570 — the owner name lives only on the owned Person. ownerName is the
|
|
310
|
+
// trimmed value that feeds the givenName/familyName split; the AdminUser
|
|
311
|
+
// carries no name.
|
|
312
|
+
{ accountId, ownerUserId, ownerName: trimmedName, givenName, familyName, createdAt });
|
|
253
313
|
const rec = res.records[0];
|
|
254
314
|
return {
|
|
255
315
|
businessSeeded: Boolean(rec?.get("hasBusiness")),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-lifecycle.js","sourceRoot":"","sources":["../../src/tools/account-lifecycle.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,sEAAsE;AACtE,gFAAgF;AAChF,+EAA+E;AAC/E,uEAAuE;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,OAAO,GAAG,iEAAiE,CAAC;
|
|
1
|
+
{"version":3,"file":"account-lifecycle.js","sourceRoot":"","sources":["../../src/tools/account-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,6 +51,46 @@ Deterministic per-admin `userId` on loopback is deliberately out of scope:
|
|
|
51
51
|
making it deterministic again means a per-session identity step, which is exactly
|
|
52
52
|
the deadlock the retirement removed.
|
|
53
53
|
|
|
54
|
+
## Credential-write identity binding
|
|
55
|
+
|
|
56
|
+
The admin MCP credential tools (`remote-auth-set-password`, `admin-update-pin`,
|
|
57
|
+
`remote-auth-revoke-password`) write the `accessHash` and `pin` fields on
|
|
58
|
+
`users.json` rows. Their operating identity is `process.env.USER_ID`, which the
|
|
59
|
+
admin MCP inherits from its parent `claude` PTY.
|
|
60
|
+
|
|
61
|
+
A prior defect stamped the wrong identity onto that env. The `/rc-spawn` handler
|
|
62
|
+
built the child `USER_ID` as `overrideUserId ?? deps.userId`, where `deps.userId`
|
|
63
|
+
is the boot-time owner. An authenticated non-owner admin whose spawn request
|
|
64
|
+
carried the authenticated `adminUserId` but no per-session `userId` therefore ran
|
|
65
|
+
with the owner's `USER_ID`, and a credential tool called with no explicit
|
|
66
|
+
`userId` rewrote the owner's row. The audit recorded the owner as the actor, so
|
|
67
|
+
it read as an owner self-change.
|
|
68
|
+
|
|
69
|
+
The binding now holds:
|
|
70
|
+
|
|
71
|
+
- `USER_ID` at `/rc-spawn` is `resolvedAdminUserId (authenticated admin) ??
|
|
72
|
+
overrideUserId ?? ''`. The owner fallback is removed. An authenticated admin
|
|
73
|
+
always wins; an unbound sender with no admin identity gets empty `USER_ID`, a
|
|
74
|
+
documented-legal value. This changes the earlier accepted boundary: an unbound
|
|
75
|
+
channel sender's rc-spawn no longer inherits the owner `userId` at the env
|
|
76
|
+
layer. The `claude rc` daemon env (not a per-session conversation) is
|
|
77
|
+
unchanged and still carries the boot owner `userId`.
|
|
78
|
+
- A credential tool with no explicit `userId` resolves to the verified caller
|
|
79
|
+
(`USER_ID`, empty treated as no identity). With no verified identity it errors
|
|
80
|
+
and writes nothing; it never substitutes an ambient env value for a missing
|
|
81
|
+
target.
|
|
82
|
+
- Writing a *different* admin's credential requires an explicit `userId` and
|
|
83
|
+
`confirm: true`. Self writes and same-identity writes need no confirm. This
|
|
84
|
+
keeps the "any admin may rotate any admin's PIN with an explicit userId" trust
|
|
85
|
+
model while making a cross-identity change a deliberate two-signal act.
|
|
86
|
+
- Every credential write records `actor` (the verified caller), `target` (the
|
|
87
|
+
row written), and `explicitUserId` in `users-audit.log`. The standing
|
|
88
|
+
signatures: `[users-audit] … actor=<x> target=<y> explicitUserId=<bool>` and,
|
|
89
|
+
per spawn, `[identity-audit] op=mcp-user-binding seat=<x> mcpUserId=<y>
|
|
90
|
+
match=<bool>`. The alarms are `actor != target && explicitUserId=false` and
|
|
91
|
+
`match=false` — a self-targeted write that hit another row, or an authenticated
|
|
92
|
+
admin whose stamped `USER_ID` differs from that admin.
|
|
93
|
+
|
|
54
94
|
## Boot-time binding drift gate
|
|
55
95
|
|
|
56
96
|
The channel-admin binding is reassembled at read time from three independently
|
package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/profile.md
CHANGED
|
@@ -86,7 +86,7 @@ The parser converts:
|
|
|
86
86
|
```cypher
|
|
87
87
|
MATCH (au:AdminUser {userId: $ownerUserId})-[:HAS_PROFILE]->(up:UserProfile)
|
|
88
88
|
RETURN
|
|
89
|
-
au.
|
|
89
|
+
au.userId,
|
|
90
90
|
up.givenName, up.familyName, up.headline, up.description,
|
|
91
91
|
up.websites, up.linkedinProfileUpdatedAt
|
|
92
92
|
```
|