instar 1.3.613 → 1.3.615
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 +58 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +11 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/AccountFollowMeRevocationStore.d.ts +34 -0
- package/dist/core/AccountFollowMeRevocationStore.d.ts.map +1 -0
- package/dist/core/AccountFollowMeRevocationStore.js +76 -0
- package/dist/core/AccountFollowMeRevocationStore.js.map +1 -0
- package/dist/core/EnrollmentWizard.d.ts +48 -0
- package/dist/core/EnrollmentWizard.d.ts.map +1 -1
- package/dist/core/EnrollmentWizard.js +66 -7
- package/dist/core/EnrollmentWizard.js.map +1 -1
- package/dist/core/FrameworkLoginDriver.d.ts +7 -0
- package/dist/core/FrameworkLoginDriver.d.ts.map +1 -1
- package/dist/core/FrameworkLoginDriver.js +12 -3
- package/dist/core/FrameworkLoginDriver.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +9 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +30 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/accountFollowMeCooperativeWipe.d.ts +66 -0
- package/dist/core/accountFollowMeCooperativeWipe.d.ts.map +1 -0
- package/dist/core/accountFollowMeCooperativeWipe.js +179 -0
- package/dist/core/accountFollowMeCooperativeWipe.js.map +1 -0
- package/dist/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +6 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +72 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/upgrades/1.3.614.md +22 -0
- package/upgrades/1.3.615.md +35 -0
- package/upgrades/side-effects/ws52-account-follow-me-r6b-reliability.md +66 -0
- package/upgrades/side-effects/ws52-account-follow-me-revocation-wiring.md +104 -0
package/dist/server/routes.js
CHANGED
|
@@ -6515,7 +6515,48 @@ export function createRoutes(ctx) {
|
|
|
6515
6515
|
res.status(404).json({ error: `mandate "${req.params.id}" not found` });
|
|
6516
6516
|
return;
|
|
6517
6517
|
}
|
|
6518
|
-
|
|
6518
|
+
// WS5.2 R12 — Account Follow-Me revocation data-plane trigger (PER-SERVER model, OQ6). The
|
|
6519
|
+
// control-plane revoke above already fired (every subsequent MandateGate.evaluate denies). If
|
|
6520
|
+
// the revoked mandate carried an `account-follow-me` authority, run THIS machine's OWN local
|
|
6521
|
+
// data-plane wipe (the operator revoked on the target's OWN dashboard ⇒ the target IS this
|
|
6522
|
+
// machine ⇒ cooperative-online posture). Non-account-follow-me mandates are completely
|
|
6523
|
+
// unaffected. Strict no-op when the executor is unwired OR the feature gate resolves dark
|
|
6524
|
+
// (revoke() returns feature-disabled and runs nothing). Surfaces the honest data-plane outcome
|
|
6525
|
+
// on the response so the operator/dashboard never sees a false "removed".
|
|
6526
|
+
let accountFollowMeRevocation;
|
|
6527
|
+
try {
|
|
6528
|
+
const followMeAuthority = (m.authorities ?? []).find((a) => a.action === 'account-follow-me');
|
|
6529
|
+
if (followMeAuthority && ctx.accountFollowMeRevocation) {
|
|
6530
|
+
const bounds = (followMeAuthority.bounds ?? {});
|
|
6531
|
+
const accountId = typeof bounds.accountId === 'string' ? bounds.accountId : '';
|
|
6532
|
+
const targetMachineId = typeof bounds.targetMachineId === 'string' ? bounds.targetMachineId : '';
|
|
6533
|
+
const mechanism = bounds.mechanism === 'credential-transport' ? 'credential-transport' : 're-mint';
|
|
6534
|
+
if (accountId && targetMachineId) {
|
|
6535
|
+
const acct = ctx.subscriptionPool?.get(accountId) ?? null;
|
|
6536
|
+
accountFollowMeRevocation = ctx.accountFollowMeRevocation.revoke({
|
|
6537
|
+
accountId,
|
|
6538
|
+
accountEmail: acct?.email ?? accountId,
|
|
6539
|
+
targetMachineId,
|
|
6540
|
+
targetMachineNickname: typeof bounds.targetMachineNickname === 'string' ? bounds.targetMachineNickname : targetMachineId,
|
|
6541
|
+
provider: acct?.provider ?? (typeof bounds.provider === 'string' ? bounds.provider : 'the provider'),
|
|
6542
|
+
mandateId: m.id,
|
|
6543
|
+
mechanism,
|
|
6544
|
+
},
|
|
6545
|
+
// PER-SERVER: the operator revoked on the target's own dashboard ⇒ target is online &
|
|
6546
|
+
// cooperative (this very machine). The local wipe runs; an offline/de-paired posture is
|
|
6547
|
+
// only reachable on the cross-machine path, which the per-server model does not use.
|
|
6548
|
+
'cooperative-online');
|
|
6549
|
+
}
|
|
6550
|
+
}
|
|
6551
|
+
}
|
|
6552
|
+
catch {
|
|
6553
|
+
// @silent-fallback-ok: the data-plane effect must never break the control-plane revoke (which
|
|
6554
|
+
// already succeeded). A wipe error is surfaced honestly INSIDE the executor (fail-closed to
|
|
6555
|
+
// pending) for the normal path; this catch is the last-resort backstop so the route always
|
|
6556
|
+
// returns the successful revoke.
|
|
6557
|
+
accountFollowMeRevocation = undefined;
|
|
6558
|
+
}
|
|
6559
|
+
res.json({ revoked: true, mandate: m, ...(accountFollowMeRevocation ? { accountFollowMeRevocation } : {}) });
|
|
6519
6560
|
});
|
|
6520
6561
|
// Add user→agent authority grant(s) to a mandate — PIN-GATED (the same human-
|
|
6521
6562
|
// authenticated surface as issuance; an agent's Bearer token cannot mint a grant).
|
|
@@ -19111,6 +19152,14 @@ export function createRoutes(ctx) {
|
|
|
19111
19152
|
res.status(201).json({ enabled: true, login });
|
|
19112
19153
|
}
|
|
19113
19154
|
catch (err) {
|
|
19155
|
+
// WS5.2 R6b — a DRIVE failure is honest + retry-able (502), NOT an opaque 500.
|
|
19156
|
+
// No pending-login was issued (the store is written only after the drive
|
|
19157
|
+
// succeeds), so the caller can simply retry.
|
|
19158
|
+
const { EnrollmentDriveError } = await import('../core/EnrollmentWizard.js');
|
|
19159
|
+
if (err instanceof EnrollmentDriveError) {
|
|
19160
|
+
res.status(502).json({ error: 'login-did-not-start', retryable: true, message: err.operatorMessage });
|
|
19161
|
+
return;
|
|
19162
|
+
}
|
|
19114
19163
|
res.status(500).json({ error: err instanceof Error ? err.message : 'failed to start enrollment' });
|
|
19115
19164
|
}
|
|
19116
19165
|
});
|
|
@@ -19220,6 +19269,14 @@ export function createRoutes(ctx) {
|
|
|
19220
19269
|
// Allocate this account's own config-home slot on THIS machine (one home per credential).
|
|
19221
19270
|
const safeAccountId = accountId.replace(/[^a-z0-9-]/gi, '-');
|
|
19222
19271
|
const configHome = path.join(os.homedir(), `.claude-followme-${safeAccountId}`);
|
|
19272
|
+
// WS5.2 R6b — this IS the remote/cloud (follow-me) enrollment path, so use the
|
|
19273
|
+
// remote-aware kind selection (device-code single-code flow where supported) and
|
|
19274
|
+
// thread the LARGER scrape-timeout budget (cloud→provider latency + the two-code
|
|
19275
|
+
// window). The budget comes from the config knob (default 180000); omitted ⇒ the
|
|
19276
|
+
// driver's local-LAN default.
|
|
19277
|
+
const remoteScrapeTimeoutMs = typeof afmCfg?.remoteScrapeTimeoutMs === 'number' && Number.isFinite(afmCfg.remoteScrapeTimeoutMs)
|
|
19278
|
+
? afmCfg.remoteScrapeTimeoutMs
|
|
19279
|
+
: undefined;
|
|
19223
19280
|
const login = await ctx.enrollmentWizard.start({
|
|
19224
19281
|
id: accountId,
|
|
19225
19282
|
label: target.label,
|
|
@@ -19227,10 +19284,24 @@ export function createRoutes(ctx) {
|
|
|
19227
19284
|
framework: target.framework,
|
|
19228
19285
|
configHome,
|
|
19229
19286
|
expectedEmail: target.expectedEmail,
|
|
19287
|
+
remote: true,
|
|
19288
|
+
remoteScrapeTimeoutMs,
|
|
19230
19289
|
});
|
|
19231
19290
|
res.status(201).json({ enabled: true, login });
|
|
19232
19291
|
}
|
|
19233
19292
|
catch (err) {
|
|
19293
|
+
// WS5.2 R6b — a DRIVE failure is honest + retry-able (502), NOT an opaque 500.
|
|
19294
|
+
// The store is written ONLY after the drive succeeds, so a drive throw leaves NO
|
|
19295
|
+
// stuck pending-login behind — the caller can simply retry the enrollment.
|
|
19296
|
+
const { EnrollmentDriveError } = await import('../core/EnrollmentWizard.js');
|
|
19297
|
+
if (err instanceof EnrollmentDriveError) {
|
|
19298
|
+
res.status(502).json({
|
|
19299
|
+
error: 'login-did-not-start',
|
|
19300
|
+
retryable: true,
|
|
19301
|
+
message: `couldn’t start the login on the target — ${err.operatorMessage}`,
|
|
19302
|
+
});
|
|
19303
|
+
return;
|
|
19304
|
+
}
|
|
19234
19305
|
res.status(500).json({ error: err instanceof Error ? err.message : 'follow-me enroll start failed' });
|
|
19235
19306
|
}
|
|
19236
19307
|
});
|