instar 1.3.834 → 1.3.835

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.
Files changed (42) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +102 -1
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/CredentialIdentityRepairPlan.d.ts +42 -0
  5. package/dist/core/CredentialIdentityRepairPlan.d.ts.map +1 -0
  6. package/dist/core/CredentialIdentityRepairPlan.js +82 -0
  7. package/dist/core/CredentialIdentityRepairPlan.js.map +1 -0
  8. package/dist/core/CredentialLocationLedger.d.ts +2 -1
  9. package/dist/core/CredentialLocationLedger.d.ts.map +1 -1
  10. package/dist/core/CredentialLocationLedger.js +15 -4
  11. package/dist/core/CredentialLocationLedger.js.map +1 -1
  12. package/dist/core/CredentialSwapExecutor.d.ts +6 -0
  13. package/dist/core/CredentialSwapExecutor.d.ts.map +1 -1
  14. package/dist/core/CredentialSwapExecutor.js +102 -0
  15. package/dist/core/CredentialSwapExecutor.js.map +1 -1
  16. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  17. package/dist/core/PostUpdateMigrator.js +14 -0
  18. package/dist/core/PostUpdateMigrator.js.map +1 -1
  19. package/dist/core/QuotaPoller.d.ts +31 -0
  20. package/dist/core/QuotaPoller.d.ts.map +1 -1
  21. package/dist/core/QuotaPoller.js +106 -10
  22. package/dist/core/QuotaPoller.js.map +1 -1
  23. package/dist/core/SubscriptionPool.d.ts +19 -0
  24. package/dist/core/SubscriptionPool.d.ts.map +1 -1
  25. package/dist/core/SubscriptionPool.js +12 -2
  26. package/dist/core/SubscriptionPool.js.map +1 -1
  27. package/dist/core/WriteDomainRegistry.d.ts.map +1 -1
  28. package/dist/core/WriteDomainRegistry.js +14 -0
  29. package/dist/core/WriteDomainRegistry.js.map +1 -1
  30. package/dist/scaffold/templates.d.ts.map +1 -1
  31. package/dist/scaffold/templates.js +1 -0
  32. package/dist/scaffold/templates.js.map +1 -1
  33. package/dist/server/routes.d.ts +19 -0
  34. package/dist/server/routes.d.ts.map +1 -1
  35. package/dist/server/routes.js +24 -0
  36. package/dist/server/routes.js.map +1 -1
  37. package/package.json +1 -1
  38. package/src/data/builtin-manifest.json +63 -63
  39. package/src/scaffold/templates.ts +1 -0
  40. package/upgrades/1.3.835.md +25 -0
  41. package/upgrades/eli16/subscription-pool-identity-repair.md +27 -0
  42. package/upgrades/side-effects/subscription-pool-identity-repair.md +129 -0
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyDH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AA0BjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA6H7D,OAAO,KAAK,EAAW,oBAAoB,EAAe,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAgFtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAkoDD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,oBAAoB,GAAG,IAAI,GACxC;IACD,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqBA;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAQrD,oBAAoB,CAAC,EAAE,MAAM;IAC3B,YAAY,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,GACP,IAAI,CAssBN;AAgmBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA83nBtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0DH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AA0BjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA6H7D,OAAO,KAAK,EAAW,oBAAoB,EAAe,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAgFtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAkoDD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,oBAAoB,GAAG,IAAI,GACxC;IACD,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqBA;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAQrD,oBAAoB,CAAC,EAAE,MAAM;IAC3B,YAAY,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,GACP,IAAI,CAssBN;AAgmBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA69nBtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -25,6 +25,7 @@ import { heartbeatFreshEnoughToRerecord } from '../core/MachineHeartbeat.js';
25
25
  import { slackRespawnBootstrapIds } from '../core/slackRefreshBinding.js';
26
26
  import { configureHostSpawnSemaphore } from '../core/hostSpawnSemaphore.js';
27
27
  import { SpawningTopicsRegistry } from '../core/SpawningTopicsRegistry.js';
28
+ import { planCredentialIdentityRepair } from '../core/CredentialIdentityRepairPlan.js';
28
29
  import { TopicReachabilityVerifier } from '../monitoring/TopicReachabilityVerifier.js';
29
30
  import { SingleInstanceLock, installReleaseHandlers } from '../core/SingleInstanceLock.js';
30
31
  import { resolveDevAgentGate, resolveStateSyncStores } from '../core/devAgentGate.js';
@@ -12037,6 +12038,7 @@ export async function startServer(options) {
12037
12038
  return { unavailable: true, reason: `ambiguous/unknown email (${matches.length} pool matches)` };
12038
12039
  return { accountId: matches[0].id };
12039
12040
  };
12041
+ let quotaPollerRef = null;
12040
12042
  const credentialSwapExecutor = new CredentialSwapExecutor({
12041
12043
  funnel: credentialWriteFunnel,
12042
12044
  ledger: credentialLocationLedger,
@@ -12051,7 +12053,7 @@ export async function startServer(options) {
12051
12053
  onSlotsChanged: (slots) => { try {
12052
12054
  inUseAccountResolver.bustCache?.();
12053
12055
  }
12054
- catch { /* @silent-fallback-ok: cache-bust is an observability nicety (a stale badge self-corrects at TTL); a throwing consumer must never break the committed swap */ } void slots; },
12056
+ catch { /* @silent-fallback-ok: cache-bust is an observability nicety (a stale badge self-corrects at TTL); a throwing consumer must never break the committed swap */ } quotaPollerRef?.invalidateIdentityCache(slots); },
12055
12057
  });
12056
12058
  const credentialManualLevers = new CredentialManualLevers({
12057
12059
  maxForcedPerWindow: config.subscriptionPool?.credentialRepointing?.maxForcedManualSwapsPerWindow,
@@ -12104,6 +12106,58 @@ export async function startServer(options) {
12104
12106
  });
12105
12107
  },
12106
12108
  });
12109
+ const buildCredentialRepairPlan = async () => {
12110
+ const accounts = subscriptionPool.list().filter((a) => a.framework === 'claude-code');
12111
+ const slots = [...new Set(accounts.map((a) => a.configHome))];
12112
+ const observations = await Promise.all(slots.map(async (slot) => {
12113
+ const identity = await credResolveIdentity(slot);
12114
+ return { slot, accountId: 'unavailable' in identity ? null : identity.accountId };
12115
+ }));
12116
+ return planCredentialIdentityRepair(accounts, observations);
12117
+ };
12118
+ const executeCredentialRepairPlan = async () => {
12119
+ const plan = await buildCredentialRepairPlan();
12120
+ const results = [];
12121
+ const vacateResults = [];
12122
+ for (const vacate of plan.vacates) {
12123
+ const result = await credentialSwapExecutor.vacateDuplicate(vacate.impostorSlot, vacate.retainedSlot, vacate.accountId);
12124
+ vacateResults.push({ ...vacate, outcome: result.outcome, reason: result.reason });
12125
+ if (result.outcome !== 'swapped' && result.outcome !== 'dry-run')
12126
+ break;
12127
+ }
12128
+ for (const move of plan.moves) {
12129
+ const [liveA, liveB] = await Promise.all([credResolveIdentity(move.slotA), credResolveIdentity(move.slotB)]);
12130
+ if ('unavailable' in liveA || 'unavailable' in liveB) {
12131
+ results.push({ move, outcome: 'precondition-failed', reason: 'repair census became unavailable — move refused' });
12132
+ break;
12133
+ }
12134
+ credentialLocationLedger.recordAssignment(move.slotA, liveA.accountId, { verifiedAt: new Date().toISOString(), op: 'reconcile', source: 'identity-repair-preflight' });
12135
+ credentialLocationLedger.recordAssignment(move.slotB, liveB.accountId, { verifiedAt: new Date().toISOString(), op: 'reconcile', source: 'identity-repair-preflight' });
12136
+ const result = await credentialSwapExecutor.swap(move.slotA, move.slotB);
12137
+ results.push({ move, outcome: result.outcome, reason: result.reason });
12138
+ if (result.outcome !== 'swapped' && result.outcome !== 'dry-run')
12139
+ break;
12140
+ }
12141
+ for (const accountId of plan.ownerReloginAccountIds) {
12142
+ const externalKey = `credential-identity-relogin:${accountId}`;
12143
+ try {
12144
+ if (!commitmentTracker.getActive().some((c) => c.externalKey === externalKey)) {
12145
+ commitmentTracker.record({
12146
+ type: 'one-time-action', source: 'agent', beaconEnabled: true, externalKey,
12147
+ userRequest: `Restore the missing local login for subscription account ${accountId}.`,
12148
+ agentResponse: `Owner re-login is required on this machine. Use the dashboard Subscriptions grid or POST /subscription-pool/follow-me/enroll/start for account ${accountId}; the login is minted locally and never copied across machines.`,
12149
+ });
12150
+ }
12151
+ subscriptionPool.update(accountId, { identityDrifted: true, identityDrift: {
12152
+ expectedAccountId: accountId, actualAccountId: 'missing-local-login',
12153
+ slot: subscriptionPool.get(accountId)?.configHome ?? 'unknown', detectedAt: new Date().toISOString(),
12154
+ lastConfirmedAt: new Date().toISOString(), repairState: 'owner-relogin-required',
12155
+ } });
12156
+ }
12157
+ catch { /* @silent-fallback-ok: next audit retries the durable residual; no credential mutation depends on it */ }
12158
+ }
12159
+ return { plan, results, vacateResults };
12160
+ };
12107
12161
  const credentialRepointing = {
12108
12162
  ledger: credentialLocationLedger,
12109
12163
  swapExecutor: credentialSwapExecutor,
@@ -12112,6 +12166,8 @@ export async function startServer(options) {
12112
12166
  levers: credentialManualLevers,
12113
12167
  envTokenGate: credentialEnvTokenGate,
12114
12168
  rebalancer: credentialRebalancer,
12169
+ repairPlan: buildCredentialRepairPlan,
12170
+ executeRepairPlan: executeCredentialRepairPlan,
12115
12171
  readBlob: async (slot) => {
12116
12172
  const raw = await defaultKeychainExec.readService(credSwapService(slot));
12117
12173
  if (!raw)
@@ -12203,6 +12259,20 @@ export async function startServer(options) {
12203
12259
  if (r.refreshed || r.recovered || r.quarantined) {
12204
12260
  console.log(pc.dim(` Credential identity audit (${trigger}): ${r.refreshed} refreshed, ${r.recovered} recovered, ${r.quarantined} quarantined, ${r.unresolved} unresolved`));
12205
12261
  }
12262
+ // A confirmed divergence is not flag-and-forget. Immediately run the
12263
+ // audited repair arm: dry-run while the feature is in dry-run, real
12264
+ // staged moves only when the existing destructive gate is live.
12265
+ if (r.quarantined > 0) {
12266
+ const repair = await executeCredentialRepairPlan();
12267
+ credentialAuditEmit.audit({
12268
+ event: 'identity-repair-auto-pass', trigger,
12269
+ moves: repair.results.length,
12270
+ outcomes: repair.results.map((x) => x.outcome),
12271
+ duplicateVacates: repair.vacateResults.length,
12272
+ vacateOutcomes: repair.vacateResults.map((x) => x.outcome),
12273
+ ownerReloginResiduals: repair.plan.ownerReloginAccountIds.length,
12274
+ });
12275
+ }
12206
12276
  }
12207
12277
  catch (e) {
12208
12278
  console.warn(`[CredentialIdentityAudit] ${trigger} error: ${e instanceof Error ? e.message : String(e)}`);
@@ -12231,7 +12301,38 @@ export async function startServer(options) {
12231
12301
  logger: { log: (m) => console.log(m), warn: (m) => console.warn(m) },
12232
12302
  // Census #1–#4: resolve each account's LIVE slot through the ledger (no-op while dark).
12233
12303
  locationGate: credentialLocationGate,
12304
+ // Tier-0 attribution hardening: reuse the SAME profile-backed identity oracle as
12305
+ // credential swaps. QuotaPoller caches this read for ~6h; the swap executor's
12306
+ // mandatory pre-flight remains live/uncached.
12307
+ resolveSlotIdentity: async (slot) => {
12308
+ const r = await credResolveIdentity(slot);
12309
+ if ('unavailable' in r)
12310
+ return r;
12311
+ const account = subscriptionPool.get(r.accountId);
12312
+ return { accountId: r.accountId, ...(account?.email ? { email: account.email } : {}) };
12313
+ },
12314
+ identityCacheTtlMs: 6 * 60 * 60_000,
12315
+ locationLedger: credentialLocationLedger,
12316
+ emitIdentityDriftAttention: telegram
12317
+ ? (item) => void telegram.createAttentionItem({
12318
+ id: item.id,
12319
+ title: item.title,
12320
+ summary: item.summary,
12321
+ description: item.summary,
12322
+ category: 'credential-identity-drift',
12323
+ priority: 'HIGH',
12324
+ sourceContext: 'quota-poll-identity-oracle',
12325
+ })
12326
+ : undefined,
12327
+ onIdentityRestored: (accountId, attentionId) => {
12328
+ const externalKey = `credential-identity-relogin:${accountId}`;
12329
+ const active = commitmentTracker.getActive().find((c) => c.externalKey === externalKey);
12330
+ if (active)
12331
+ commitmentTracker.deliver(active.id);
12332
+ void telegram?.updateAttentionStatus(attentionId, 'DONE', { silent: true }).catch(() => { });
12333
+ },
12234
12334
  });
12335
+ quotaPollerRef = quotaPoller;
12235
12336
  if (subscriptionPool.size() > 0) {
12236
12337
  quotaPoller.start();
12237
12338
  console.log(pc.green(' Subscription quota poller started'));