instar 1.3.725 → 1.3.727
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +45 -4
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +1 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +19 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +4 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/messaging/slack/SlackAdapter.d.ts +15 -0
- package/dist/messaging/slack/SlackAdapter.d.ts.map +1 -1
- package/dist/messaging/slack/SlackAdapter.js +20 -2
- package/dist/messaging/slack/SlackAdapter.js.map +1 -1
- package/dist/messaging/slack/types.d.ts +38 -0
- package/dist/messaging/slack/types.d.ts.map +1 -1
- package/dist/messaging/slack/types.js +4 -0
- package/dist/messaging/slack/types.js.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.d.ts +12 -0
- package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.js +19 -0
- package/dist/monitoring/AgentWorktreeReaper.js.map +1 -1
- package/dist/permissions/TestWorkspacePrincipalSource.d.ts +133 -0
- package/dist/permissions/TestWorkspacePrincipalSource.d.ts.map +1 -0
- package/dist/permissions/TestWorkspacePrincipalSource.js +189 -0
- package/dist/permissions/TestWorkspacePrincipalSource.js.map +1 -0
- package/dist/permissions/index.d.ts +1 -0
- package/dist/permissions/index.d.ts.map +1 -1
- package/dist/permissions/index.js +1 -0
- package/dist/permissions/index.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +19 -19
- package/upgrades/1.3.727.md +143 -0
- package/upgrades/side-effects/reaper-initial-pass.md +103 -0
- package/upgrades/side-effects/slack-test-workspace-principal-source.md +227 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestWorkspacePrincipalSource — the sanctioned, workspace-scoped principal source
|
|
3
|
+
* for the Slack live-test scenario cast (roadmap 0.3 entry condition).
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS (the 2026-07-01 lesson): the June scenario drives seeded the
|
|
6
|
+
* five-seat test cast into the production user registry (`users.json`). The
|
|
7
|
+
* silent-loss registry rebuild removed them, and the fixture-identity guard
|
|
8
|
+
* ("Test Identity Never Enters Production State", silent-loss-refusal-conservation
|
|
9
|
+
* §2.D) now — correctly — refuses to let them back in. Principal resolution for
|
|
10
|
+
* the live-test workspace therefore needs a home that is NOT the production
|
|
11
|
+
* registry. This module is that home.
|
|
12
|
+
*
|
|
13
|
+
* THE PARTITION INVARIANT (the load-bearing design decision):
|
|
14
|
+
* - The production registry REFUSES fixture identities (the existing guard,
|
|
15
|
+
* untouched by this module).
|
|
16
|
+
* - This source ACCEPTS ONLY fixture identities — every cast entry's
|
|
17
|
+
* slackUserId must match the SAME single matcher the production guard uses
|
|
18
|
+
* (`matchesTestIdentityToken` from `users/testIdentityMarkers.ts`). A
|
|
19
|
+
* non-fixture UID is refused at load, loudly.
|
|
20
|
+
* By construction an identity can live in exactly one of the two stores —
|
|
21
|
+
* a real employee's UID can never be smuggled into the cast to gain a role
|
|
22
|
+
* outside the audited registration path, and standing up a NEW test cast
|
|
23
|
+
* structurally forces the fixture-marker list to be updated first (which is
|
|
24
|
+
* what keeps the production guard aware of the new fixtures). The single
|
|
25
|
+
* matcher can never drift into two lists.
|
|
26
|
+
*
|
|
27
|
+
* THE SELF-DECLARATION MARKER (fail-closed to ignoring the cast): the config
|
|
28
|
+
* object MUST self-declare `testWorkspace: true`. Without that marker the source
|
|
29
|
+
* refuses to load a SINGLE principal — it disables itself, emits ONE loud log
|
|
30
|
+
* line, and every lookup returns null (production resolution is byte-identical to
|
|
31
|
+
* having no cast at all). The marker exists so a cast config can never be
|
|
32
|
+
* activated by accident: sanctioning a live-test workspace is a deliberate,
|
|
33
|
+
* self-evident opt-in, never an implicit side effect of the block existing.
|
|
34
|
+
*
|
|
35
|
+
* SCOPING (fail-closed): the cast resolves ONLY while the Slack adapter's
|
|
36
|
+
* VERIFIED connected team id (captured from Slack's own `auth.test` response at
|
|
37
|
+
* adapter start — never from config alone) equals the configured test
|
|
38
|
+
* `workspaceId`. Before verification, on verification failure, or when the
|
|
39
|
+
* adapter is connected to any other workspace, every lookup returns null and
|
|
40
|
+
* the resolver falls through to its existing safe default (unregistered guest).
|
|
41
|
+
*
|
|
42
|
+
* READ-ONLY BY DESIGN: this source never writes anything — not users.json, not
|
|
43
|
+
* a state file. It is consulted ONLY by the permission gate's principal
|
|
44
|
+
* resolver (production-registry-first via {@link ChainedUserLookup}); it is
|
|
45
|
+
* invisible to UserManager, sender auth (`authorizedUserIds`), cross-machine
|
|
46
|
+
* replication, and every other identity surface.
|
|
47
|
+
*
|
|
48
|
+
* Note on imports: `testIdentityMarkers.ts` is dependency-light (node builtins +
|
|
49
|
+
* a type-only core import), so reusing its matcher keeps the permission module
|
|
50
|
+
* free of runtime core dependencies — and keeps ONE fixture matcher, not two.
|
|
51
|
+
*
|
|
52
|
+
* Design: docs/specs/SLACK-ORG-INTEGRATION-SPEC.md §6.2.1;
|
|
53
|
+
* runbook: docs/specs/SLACK-ORG-TEST-WORKSPACE-RUNBOOK.md.
|
|
54
|
+
*/
|
|
55
|
+
import type { ResolvedUserRecord, UserLookup } from './SlackPrincipalResolver.js';
|
|
56
|
+
/** One seat of the live-test scenario cast (configured in the Slack config block). */
|
|
57
|
+
export interface TestCastEntry {
|
|
58
|
+
/** The seat's REAL Slack user id in the live-test workspace (must be a fixture-marker id). */
|
|
59
|
+
slackUserId: string;
|
|
60
|
+
/** Display name for conversational messages — never a basis for authority. */
|
|
61
|
+
name?: string;
|
|
62
|
+
/** The org role this seat plays (owner / admin / member / contributor / …). */
|
|
63
|
+
orgRole: string;
|
|
64
|
+
}
|
|
65
|
+
/** Why a configured cast entry was refused at load. */
|
|
66
|
+
export interface RejectedCastEntry {
|
|
67
|
+
slackUserId: string;
|
|
68
|
+
reason: 'missing-slack-user-id' | 'not-a-fixture-identity' | 'invalid-role' | 'duplicate' | 'cast-cap-exceeded';
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Hard ceiling on cast seats. The scenario cast is five seats today; the cap
|
|
72
|
+
* exists so the test-cast path can never quietly become a shadow user registry.
|
|
73
|
+
*/
|
|
74
|
+
export declare const MAX_TEST_CAST_SEATS = 12;
|
|
75
|
+
export interface TestWorkspacePrincipalSourceOpts {
|
|
76
|
+
/** The sanctioned live-test workspace/team id (T…) this cast is scoped to. */
|
|
77
|
+
workspaceId: string;
|
|
78
|
+
/**
|
|
79
|
+
* The REQUIRED self-declaration marker. The source refuses to load ANY
|
|
80
|
+
* principal unless this is exactly `true` — fail-closed to ignoring the cast
|
|
81
|
+
* (one loud log line, never a crash, never a production-registry effect).
|
|
82
|
+
*/
|
|
83
|
+
testWorkspace: boolean;
|
|
84
|
+
/** The configured cast seats. Invalid entries are refused (see {@link RejectedCastEntry}). */
|
|
85
|
+
principals: TestCastEntry[];
|
|
86
|
+
/**
|
|
87
|
+
* Supplier of the adapter's VERIFIED connected team id (from `auth.test`).
|
|
88
|
+
* Returning null/undefined (not yet verified, verification failed) keeps the
|
|
89
|
+
* source inert — fail-closed to the resolver's unregistered-guest default.
|
|
90
|
+
*/
|
|
91
|
+
getVerifiedWorkspaceId: () => string | null | undefined;
|
|
92
|
+
}
|
|
93
|
+
/** Why the whole source was disabled at construction (loads zero principals). */
|
|
94
|
+
export type TestCastDisabledReason = 'missing-testWorkspace-marker';
|
|
95
|
+
export declare class TestWorkspacePrincipalSource implements UserLookup {
|
|
96
|
+
private readonly bySlackId;
|
|
97
|
+
private readonly workspaceId;
|
|
98
|
+
private readonly getVerifiedWorkspaceId;
|
|
99
|
+
/** Entries refused at load (surfaced loudly by the wiring site). */
|
|
100
|
+
readonly rejected: RejectedCastEntry[];
|
|
101
|
+
/**
|
|
102
|
+
* True when the whole source refused to load (the self-declaration marker was
|
|
103
|
+
* absent). A disabled source holds ZERO principals and resolves everything to
|
|
104
|
+
* null — production resolution is byte-identical to having no cast configured.
|
|
105
|
+
*/
|
|
106
|
+
readonly disabled: boolean;
|
|
107
|
+
/** Why the source disabled itself (only set when {@link disabled} is true). */
|
|
108
|
+
readonly disabledReason?: TestCastDisabledReason;
|
|
109
|
+
constructor(opts: TestWorkspacePrincipalSourceOpts);
|
|
110
|
+
/** Number of admitted cast seats. */
|
|
111
|
+
get size(): number;
|
|
112
|
+
/**
|
|
113
|
+
* Resolve a cast seat — ONLY while the verified connected workspace equals the
|
|
114
|
+
* sanctioned test workspace. Any uncertainty (no verified id yet, supplier
|
|
115
|
+
* throw, mismatch) resolves null: fail-closed to unregistered guest.
|
|
116
|
+
*/
|
|
117
|
+
resolveFromSlackUserId(slackUserId: string): ResolvedUserRecord | null;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* ChainedUserLookup — production-registry-first principal resolution.
|
|
121
|
+
*
|
|
122
|
+
* Sources are consulted in order; the first non-null record wins. The wiring
|
|
123
|
+
* site puts the production registry FIRST, so a genuinely registered user can
|
|
124
|
+
* never be shadowed or role-escalated by a cast entry, and the cast is only
|
|
125
|
+
* ever a fallback for identities the production registry does not know.
|
|
126
|
+
* A throwing source is skipped (resolution must never break the message path).
|
|
127
|
+
*/
|
|
128
|
+
export declare class ChainedUserLookup implements UserLookup {
|
|
129
|
+
private readonly sources;
|
|
130
|
+
constructor(sources: UserLookup[]);
|
|
131
|
+
resolveFromSlackUserId(slackUserId: string): ResolvedUserRecord | null;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=TestWorkspacePrincipalSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestWorkspacePrincipalSource.d.ts","sourceRoot":"","sources":["../../src/permissions/TestWorkspacePrincipalSource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAElF,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EACF,uBAAuB,GACvB,wBAAwB,GACxB,cAAc,GACd,WAAW,GACX,mBAAmB,CAAC;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,MAAM,WAAW,gCAAgC;IAC/C,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,8FAA8F;IAC9F,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACzD;AAED,iFAAiF;AACjF,MAAM,MAAM,sBAAsB,GAAG,8BAA8B,CAAC;AAEpE,qBAAa,4BAA6B,YAAW,UAAU;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAkC;IACzE,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,EAAE,CAAM;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAS;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC;gBAErC,IAAI,EAAE,gCAAgC;IA8DlD,qCAAqC;IACrC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;OAIG;IACH,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;CAcvE;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAkB,YAAW,UAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,UAAU,EAAE;IAElD,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;CAYvE"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestWorkspacePrincipalSource — the sanctioned, workspace-scoped principal source
|
|
3
|
+
* for the Slack live-test scenario cast (roadmap 0.3 entry condition).
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS (the 2026-07-01 lesson): the June scenario drives seeded the
|
|
6
|
+
* five-seat test cast into the production user registry (`users.json`). The
|
|
7
|
+
* silent-loss registry rebuild removed them, and the fixture-identity guard
|
|
8
|
+
* ("Test Identity Never Enters Production State", silent-loss-refusal-conservation
|
|
9
|
+
* §2.D) now — correctly — refuses to let them back in. Principal resolution for
|
|
10
|
+
* the live-test workspace therefore needs a home that is NOT the production
|
|
11
|
+
* registry. This module is that home.
|
|
12
|
+
*
|
|
13
|
+
* THE PARTITION INVARIANT (the load-bearing design decision):
|
|
14
|
+
* - The production registry REFUSES fixture identities (the existing guard,
|
|
15
|
+
* untouched by this module).
|
|
16
|
+
* - This source ACCEPTS ONLY fixture identities — every cast entry's
|
|
17
|
+
* slackUserId must match the SAME single matcher the production guard uses
|
|
18
|
+
* (`matchesTestIdentityToken` from `users/testIdentityMarkers.ts`). A
|
|
19
|
+
* non-fixture UID is refused at load, loudly.
|
|
20
|
+
* By construction an identity can live in exactly one of the two stores —
|
|
21
|
+
* a real employee's UID can never be smuggled into the cast to gain a role
|
|
22
|
+
* outside the audited registration path, and standing up a NEW test cast
|
|
23
|
+
* structurally forces the fixture-marker list to be updated first (which is
|
|
24
|
+
* what keeps the production guard aware of the new fixtures). The single
|
|
25
|
+
* matcher can never drift into two lists.
|
|
26
|
+
*
|
|
27
|
+
* THE SELF-DECLARATION MARKER (fail-closed to ignoring the cast): the config
|
|
28
|
+
* object MUST self-declare `testWorkspace: true`. Without that marker the source
|
|
29
|
+
* refuses to load a SINGLE principal — it disables itself, emits ONE loud log
|
|
30
|
+
* line, and every lookup returns null (production resolution is byte-identical to
|
|
31
|
+
* having no cast at all). The marker exists so a cast config can never be
|
|
32
|
+
* activated by accident: sanctioning a live-test workspace is a deliberate,
|
|
33
|
+
* self-evident opt-in, never an implicit side effect of the block existing.
|
|
34
|
+
*
|
|
35
|
+
* SCOPING (fail-closed): the cast resolves ONLY while the Slack adapter's
|
|
36
|
+
* VERIFIED connected team id (captured from Slack's own `auth.test` response at
|
|
37
|
+
* adapter start — never from config alone) equals the configured test
|
|
38
|
+
* `workspaceId`. Before verification, on verification failure, or when the
|
|
39
|
+
* adapter is connected to any other workspace, every lookup returns null and
|
|
40
|
+
* the resolver falls through to its existing safe default (unregistered guest).
|
|
41
|
+
*
|
|
42
|
+
* READ-ONLY BY DESIGN: this source never writes anything — not users.json, not
|
|
43
|
+
* a state file. It is consulted ONLY by the permission gate's principal
|
|
44
|
+
* resolver (production-registry-first via {@link ChainedUserLookup}); it is
|
|
45
|
+
* invisible to UserManager, sender auth (`authorizedUserIds`), cross-machine
|
|
46
|
+
* replication, and every other identity surface.
|
|
47
|
+
*
|
|
48
|
+
* Note on imports: `testIdentityMarkers.ts` is dependency-light (node builtins +
|
|
49
|
+
* a type-only core import), so reusing its matcher keeps the permission module
|
|
50
|
+
* free of runtime core dependencies — and keeps ONE fixture matcher, not two.
|
|
51
|
+
*
|
|
52
|
+
* Design: docs/specs/SLACK-ORG-INTEGRATION-SPEC.md §6.2.1;
|
|
53
|
+
* runbook: docs/specs/SLACK-ORG-TEST-WORKSPACE-RUNBOOK.md.
|
|
54
|
+
*/
|
|
55
|
+
import { matchesTestIdentityToken } from '../users/testIdentityMarkers.js';
|
|
56
|
+
import { ORG_ROLES } from './types.js';
|
|
57
|
+
/**
|
|
58
|
+
* Hard ceiling on cast seats. The scenario cast is five seats today; the cap
|
|
59
|
+
* exists so the test-cast path can never quietly become a shadow user registry.
|
|
60
|
+
*/
|
|
61
|
+
export const MAX_TEST_CAST_SEATS = 12;
|
|
62
|
+
export class TestWorkspacePrincipalSource {
|
|
63
|
+
bySlackId = new Map();
|
|
64
|
+
workspaceId;
|
|
65
|
+
getVerifiedWorkspaceId;
|
|
66
|
+
/** Entries refused at load (surfaced loudly by the wiring site). */
|
|
67
|
+
rejected = [];
|
|
68
|
+
/**
|
|
69
|
+
* True when the whole source refused to load (the self-declaration marker was
|
|
70
|
+
* absent). A disabled source holds ZERO principals and resolves everything to
|
|
71
|
+
* null — production resolution is byte-identical to having no cast configured.
|
|
72
|
+
*/
|
|
73
|
+
disabled = false;
|
|
74
|
+
/** Why the source disabled itself (only set when {@link disabled} is true). */
|
|
75
|
+
disabledReason;
|
|
76
|
+
constructor(opts) {
|
|
77
|
+
if (!opts.workspaceId || typeof opts.workspaceId !== 'string' || !opts.workspaceId.trim()) {
|
|
78
|
+
throw new Error('TestWorkspacePrincipalSource requires a non-empty workspaceId (the sanctioned live-test workspace)');
|
|
79
|
+
}
|
|
80
|
+
// Stored TRIMMED (second-pass review note): Slack's own `team_id` never
|
|
81
|
+
// carries whitespace, so a config value with a stray space would otherwise
|
|
82
|
+
// make the scope equality permanently false — an inert cast (fail-closed,
|
|
83
|
+
// but a silent config foot-gun the boot log alone would have to catch).
|
|
84
|
+
this.workspaceId = opts.workspaceId.trim();
|
|
85
|
+
this.getVerifiedWorkspaceId = opts.getVerifiedWorkspaceId;
|
|
86
|
+
// THE SELF-DECLARATION GATE (fail-closed): without an explicit
|
|
87
|
+
// `testWorkspace: true` the cast is IGNORED entirely — zero principals
|
|
88
|
+
// loaded, one loud line, no throw, no production impact. The loud line lives
|
|
89
|
+
// HERE (not only at the wiring site) so the fail-closed guarantee holds for
|
|
90
|
+
// EVERY caller — Structure > Willpower.
|
|
91
|
+
if (opts.testWorkspace !== true) {
|
|
92
|
+
this.disabled = true;
|
|
93
|
+
this.disabledReason = 'missing-testWorkspace-marker';
|
|
94
|
+
console.warn(`[slack] TestWorkspacePrincipalSource IGNORED for workspace ${this.workspaceId} — the testCast config is ` +
|
|
95
|
+
`missing its required "testWorkspace: true" self-declaration. Loading ZERO cast principals (fail-closed; the ` +
|
|
96
|
+
`production user registry is unaffected). Add "testWorkspace": true to sanction the live-test cast.`);
|
|
97
|
+
return; // no principals admitted
|
|
98
|
+
}
|
|
99
|
+
for (const entry of opts.principals ?? []) {
|
|
100
|
+
const slackUserId = typeof entry?.slackUserId === 'string' ? entry.slackUserId.trim() : '';
|
|
101
|
+
if (!slackUserId) {
|
|
102
|
+
this.rejected.push({ slackUserId: String(entry?.slackUserId ?? ''), reason: 'missing-slack-user-id' });
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
// THE PARTITION INVARIANT: only fixture-marker identities are admitted.
|
|
106
|
+
// Same single matcher as the production guard — never a second list.
|
|
107
|
+
if (!matchesTestIdentityToken(slackUserId)) {
|
|
108
|
+
this.rejected.push({ slackUserId, reason: 'not-a-fixture-identity' });
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (!entry.orgRole || !ORG_ROLES.includes(entry.orgRole)) {
|
|
112
|
+
this.rejected.push({ slackUserId, reason: 'invalid-role' });
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (this.bySlackId.has(slackUserId)) {
|
|
116
|
+
this.rejected.push({ slackUserId, reason: 'duplicate' });
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (this.bySlackId.size >= MAX_TEST_CAST_SEATS) {
|
|
120
|
+
this.rejected.push({ slackUserId, reason: 'cast-cap-exceeded' });
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
this.bySlackId.set(slackUserId, {
|
|
124
|
+
// Namespaced id so a cast principal is visibly a test seat in every
|
|
125
|
+
// ledger row / audit surface it appears in.
|
|
126
|
+
id: `test-cast:${slackUserId}`,
|
|
127
|
+
name: entry.name?.trim() || slackUserId,
|
|
128
|
+
permissions: [entry.orgRole],
|
|
129
|
+
orgRole: entry.orgRole,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Number of admitted cast seats. */
|
|
134
|
+
get size() {
|
|
135
|
+
return this.bySlackId.size;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Resolve a cast seat — ONLY while the verified connected workspace equals the
|
|
139
|
+
* sanctioned test workspace. Any uncertainty (no verified id yet, supplier
|
|
140
|
+
* throw, mismatch) resolves null: fail-closed to unregistered guest.
|
|
141
|
+
*/
|
|
142
|
+
resolveFromSlackUserId(slackUserId) {
|
|
143
|
+
// A disabled source (missing marker) holds no principals — this is redundant
|
|
144
|
+
// with the empty map but makes the fail-closed contract explicit.
|
|
145
|
+
if (this.disabled)
|
|
146
|
+
return null;
|
|
147
|
+
let verified;
|
|
148
|
+
try {
|
|
149
|
+
verified = this.getVerifiedWorkspaceId();
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Fail-closed: an errored verification supplier keeps the cast inert.
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
if (!verified || verified !== this.workspaceId)
|
|
156
|
+
return null;
|
|
157
|
+
return this.bySlackId.get(slackUserId) ?? null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* ChainedUserLookup — production-registry-first principal resolution.
|
|
162
|
+
*
|
|
163
|
+
* Sources are consulted in order; the first non-null record wins. The wiring
|
|
164
|
+
* site puts the production registry FIRST, so a genuinely registered user can
|
|
165
|
+
* never be shadowed or role-escalated by a cast entry, and the cast is only
|
|
166
|
+
* ever a fallback for identities the production registry does not know.
|
|
167
|
+
* A throwing source is skipped (resolution must never break the message path).
|
|
168
|
+
*/
|
|
169
|
+
export class ChainedUserLookup {
|
|
170
|
+
sources;
|
|
171
|
+
constructor(sources) {
|
|
172
|
+
this.sources = sources;
|
|
173
|
+
}
|
|
174
|
+
resolveFromSlackUserId(slackUserId) {
|
|
175
|
+
for (const source of this.sources) {
|
|
176
|
+
try {
|
|
177
|
+
const record = source.resolveFromSlackUserId(slackUserId);
|
|
178
|
+
if (record)
|
|
179
|
+
return record;
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
// A faulty source must never break principal resolution — fall through
|
|
183
|
+
// to the next source (ultimately the unregistered-guest default).
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=TestWorkspacePrincipalSource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestWorkspacePrincipalSource.js","sourceRoot":"","sources":["../../src/permissions/TestWorkspacePrincipalSource.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,4 +16,5 @@ export * from './MandateBackedGrantStore.js';
|
|
|
16
16
|
export * from './SlackPrincipalResolver.js';
|
|
17
17
|
export * from './SlackPermissionObserver.js';
|
|
18
18
|
export * from './SlackUserRegistry.js';
|
|
19
|
+
export * from './TestWorkspacePrincipalSource.js';
|
|
19
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mCAAmC,CAAC"}
|
|
@@ -16,4 +16,5 @@ export * from './MandateBackedGrantStore.js';
|
|
|
16
16
|
export * from './SlackPrincipalResolver.js';
|
|
17
17
|
export * from './SlackPermissionObserver.js';
|
|
18
18
|
export * from './SlackUserRegistry.js';
|
|
19
|
+
export * from './TestWorkspacePrincipalSource.js';
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mCAAmC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-07-03T01:19:27.750Z",
|
|
5
|
+
"instarVersion": "1.3.727",
|
|
6
6
|
"entryCount": 202,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"domain": "identity",
|
|
12
12
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
13
13
|
"installedPath": ".instar/hooks/instar/session-start.sh",
|
|
14
|
-
"contentHash": "
|
|
14
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
15
15
|
"since": "2025-01-01"
|
|
16
16
|
},
|
|
17
17
|
"hook:dangerous-command-guard": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"domain": "safety",
|
|
21
21
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
22
22
|
"installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
|
|
23
|
-
"contentHash": "
|
|
23
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
24
24
|
"since": "2025-01-01"
|
|
25
25
|
},
|
|
26
26
|
"hook:grounding-before-messaging": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"domain": "safety",
|
|
30
30
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
31
31
|
"installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
|
|
32
|
-
"contentHash": "
|
|
32
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
33
33
|
"since": "2025-01-01"
|
|
34
34
|
},
|
|
35
35
|
"hook:compaction-recovery": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"domain": "identity",
|
|
39
39
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
40
40
|
"installedPath": ".instar/hooks/instar/compaction-recovery.sh",
|
|
41
|
-
"contentHash": "
|
|
41
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
42
42
|
"since": "2025-01-01"
|
|
43
43
|
},
|
|
44
44
|
"hook:external-operation-gate": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"domain": "safety",
|
|
48
48
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
49
49
|
"installedPath": ".instar/hooks/instar/external-operation-gate.js",
|
|
50
|
-
"contentHash": "
|
|
50
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
51
51
|
"since": "2025-01-01"
|
|
52
52
|
},
|
|
53
53
|
"hook:deferral-detector": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"domain": "safety",
|
|
57
57
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
58
58
|
"installedPath": ".instar/hooks/instar/deferral-detector.js",
|
|
59
|
-
"contentHash": "
|
|
59
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
60
60
|
"since": "2025-01-01"
|
|
61
61
|
},
|
|
62
62
|
"hook:self-stop-guard": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"domain": "coherence",
|
|
66
66
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
67
67
|
"installedPath": ".instar/hooks/instar/self-stop-guard.js",
|
|
68
|
-
"contentHash": "
|
|
68
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
69
69
|
"since": "2025-01-01"
|
|
70
70
|
},
|
|
71
71
|
"hook:post-action-reflection": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"domain": "evolution",
|
|
75
75
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
76
76
|
"installedPath": ".instar/hooks/instar/post-action-reflection.js",
|
|
77
|
-
"contentHash": "
|
|
77
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
78
78
|
"since": "2025-01-01"
|
|
79
79
|
},
|
|
80
80
|
"hook:external-communication-guard": {
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"domain": "safety",
|
|
84
84
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
85
85
|
"installedPath": ".instar/hooks/instar/external-communication-guard.js",
|
|
86
|
-
"contentHash": "
|
|
86
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
87
87
|
"since": "2025-01-01"
|
|
88
88
|
},
|
|
89
89
|
"hook:scope-coherence-collector": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"domain": "coherence",
|
|
93
93
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
94
94
|
"installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
|
|
95
|
-
"contentHash": "
|
|
95
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
96
96
|
"since": "2025-01-01"
|
|
97
97
|
},
|
|
98
98
|
"hook:scope-coherence-checkpoint": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"domain": "coherence",
|
|
102
102
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
103
103
|
"installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
|
|
104
|
-
"contentHash": "
|
|
104
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
105
105
|
"since": "2025-01-01"
|
|
106
106
|
},
|
|
107
107
|
"hook:free-text-guard": {
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"domain": "safety",
|
|
111
111
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
112
112
|
"installedPath": ".instar/hooks/instar/free-text-guard.sh",
|
|
113
|
-
"contentHash": "
|
|
113
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
114
114
|
"since": "2025-01-01"
|
|
115
115
|
},
|
|
116
116
|
"hook:claim-intercept": {
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"domain": "coherence",
|
|
120
120
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
121
121
|
"installedPath": ".instar/hooks/instar/claim-intercept.js",
|
|
122
|
-
"contentHash": "
|
|
122
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
123
123
|
"since": "2025-01-01"
|
|
124
124
|
},
|
|
125
125
|
"hook:claim-intercept-response": {
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"domain": "coherence",
|
|
129
129
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
130
130
|
"installedPath": ".instar/hooks/instar/claim-intercept-response.js",
|
|
131
|
-
"contentHash": "
|
|
131
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
132
132
|
"since": "2025-01-01"
|
|
133
133
|
},
|
|
134
134
|
"hook:stop-gate-router": {
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"domain": "safety",
|
|
138
138
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
139
139
|
"installedPath": ".instar/hooks/instar/stop-gate-router.js",
|
|
140
|
-
"contentHash": "
|
|
140
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
141
141
|
"since": "2025-01-01"
|
|
142
142
|
},
|
|
143
143
|
"hook:auto-approve-permissions": {
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"domain": "safety",
|
|
147
147
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
148
148
|
"installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
|
|
149
|
-
"contentHash": "
|
|
149
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
150
150
|
"since": "2025-01-01"
|
|
151
151
|
},
|
|
152
152
|
"job:health-check": {
|
|
@@ -1562,7 +1562,7 @@
|
|
|
1562
1562
|
"type": "subsystem",
|
|
1563
1563
|
"domain": "updates",
|
|
1564
1564
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1565
|
-
"contentHash": "
|
|
1565
|
+
"contentHash": "c6ef2159621a94275497e37919cd6c33a09131e5e3a111c08b182e612f4796ae",
|
|
1566
1566
|
"since": "2025-01-01"
|
|
1567
1567
|
},
|
|
1568
1568
|
"subsystem:scheduler": {
|