dorkos 0.92.0 → 0.93.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.
Files changed (92) hide show
  1. package/core-extensions/hello-world/index.ts +69 -4
  2. package/dist/bin/cli.js +1199 -319
  3. package/dist/client/assets/{AboutPage-CtAhGJVI.js → AboutPage-R35A-Uu-.js} +1 -1
  4. package/dist/client/assets/{AdapterIcon-DTXuj6Zu.js → AdapterIcon-kPDXiFU1.js} +1 -1
  5. package/dist/client/assets/{AppearancePage-EJF8LarY.js → AppearancePage-COqDtruX.js} +1 -1
  6. package/dist/client/assets/{BaseTanStackRouterDevtoolsPanel-B-iktbLX-COy_dBa2.js → BaseTanStackRouterDevtoolsPanel-B-iktbLX-CIKvkn5X.js} +24 -24
  7. package/dist/client/assets/{BlintzCanvas-Bb84mtl-.js → BlintzCanvas-4FX_eaSh.js} +1 -1
  8. package/dist/client/assets/{CanvasCsvContent-D1y22lqg.js → CanvasCsvContent-Dq2X1kUl.js} +1 -1
  9. package/dist/client/assets/{CanvasFileContent-CbOnIUPF.js → CanvasFileContent-CZUc62IR.js} +2 -2
  10. package/dist/client/assets/{CanvasModel3dContent-Bv86PZ-y.js → CanvasModel3dContent-D1IN_nl9.js} +2 -2
  11. package/dist/client/assets/{CodeMirrorDiff-CXqMnztG.js → CodeMirrorDiff-BeEhMSvL.js} +1 -1
  12. package/dist/client/assets/{CodeMirrorEditor-DHSY565t.js → CodeMirrorEditor-BlNLMvbo.js} +1 -1
  13. package/dist/client/assets/{ConnectionAccessLists-D5Qo1i-D.js → ConnectionAccessLists-s7RnRr1y.js} +1 -1
  14. package/dist/client/assets/{ConnectionsPage-DFvJRdx7.js → ConnectionsPage-BTTdQBdS.js} +2 -2
  15. package/dist/client/assets/ConventionPage-CI3PeUHm.js +11 -0
  16. package/dist/client/assets/{FloatingTanStackRouterDevtools-CqogiFob-BDQA6n2J.js → FloatingTanStackRouterDevtools-CqogiFob-D6OvDT9K.js} +1 -1
  17. package/dist/client/assets/HandlePage-Dvqztr0N.js +1 -0
  18. package/dist/client/assets/{LexicalField-a7Ov2ETq.js → LexicalField-Bqq5KeUW.js} +1 -1
  19. package/dist/client/assets/{ManagesPage-Czapr6qD.js → ManagesPage-CWdKDvw1.js} +1 -1
  20. package/dist/client/assets/{Model3dViewer-C_lFbWIi.js → Model3dViewer-ClJVGLDb.js} +1 -1
  21. package/dist/client/assets/NamePage-BgVZ-KD1.js +1 -0
  22. package/dist/client/assets/{NotificationsPage-CdQCyMJk.js → NotificationsPage-C6tE8iuE.js} +1 -1
  23. package/dist/client/assets/{PermissionsPage-DLT-RkUE.js → PermissionsPage-BqDl7shN.js} +1 -1
  24. package/dist/client/assets/{PersonalityPopover-BeOdD7eK.js → PersonalityPopover-B3q8QYcS.js} +1 -1
  25. package/dist/client/assets/PhotoPage-lt6ZevHW.js +1 -0
  26. package/dist/client/assets/{RoomsPage-CuZJdN_k.js → RoomsPage-DwYtOhd7.js} +1 -1
  27. package/dist/client/assets/{RunsOnPopover-DspQEAdG.js → RunsOnPopover-BDPs-RYB.js} +1 -1
  28. package/dist/client/assets/{SessionsPage-Ctwlg7GN.js → SessionsPage-Du24E934.js} +2 -2
  29. package/dist/client/assets/{SkillsPage-DJdFnWfL.js → SkillsPage-DjLUEngt.js} +1 -1
  30. package/dist/client/assets/{TasksPage-9jCfZB7f.js → TasksPage-B6i3r76o.js} +1 -1
  31. package/dist/client/assets/{ToolsPage-W7zK5P0s.js → ToolsPage-DNoC2MMz.js} +2 -2
  32. package/dist/client/assets/{TopologyGraph-CQga4Nuw.js → TopologyGraph-DtBDaHqX.js} +1 -1
  33. package/dist/client/assets/{agent-browser-CoSmBP5N.js → agent-browser-da9rKrej.js} +1 -1
  34. package/dist/client/assets/{highlighted-body-KPVGNVTW-Bq_O6Zlj.js → highlighted-body-KPVGNVTW-DJ5Xz8gv.js} +1 -1
  35. package/dist/client/assets/{index-CKY7hz-9.js → index-1o6WO7iZ.js} +1 -1
  36. package/dist/client/assets/{index-Dx0uYGgf.js → index-3DE2Q3OD.js} +1 -1
  37. package/dist/client/assets/index-B5yJddXH.js +1 -0
  38. package/dist/client/assets/{index-DrD7x9EL.js → index-BC9LsNlJ.js} +1 -1
  39. package/dist/client/assets/{index-bYhLX3oQ.js → index-BCGiD7pg.js} +410 -405
  40. package/dist/client/assets/index-BG-HtbEP.css +1 -0
  41. package/dist/client/assets/{index-BBMfKdj-.js → index-BQ-o6bQ0.js} +1 -1
  42. package/dist/client/assets/{index-D4nkiaT7.js → index-BVpHI-1y.js} +1 -1
  43. package/dist/client/assets/{index-DCmzSFWM.js → index-Bl2j_xjE.js} +1 -1
  44. package/dist/client/assets/{index-THAVeZRE.js → index-BnORUrPC.js} +1 -1
  45. package/dist/client/assets/{index-OidZkt6z.js → index-Bp2CiCey.js} +1 -1
  46. package/dist/client/assets/{index-BfoOBbWz.js → index-Bu16-jWo.js} +1 -1
  47. package/dist/client/assets/{index-DT9R_NnS.js → index-BzDP7VXZ.js} +1 -1
  48. package/dist/client/assets/{index-Bj32H2Xz.js → index-C9wgMNj5.js} +3 -3
  49. package/dist/client/assets/{index-CpCOMkMm.js → index-CJK5Iw50.js} +1 -1
  50. package/dist/client/assets/{index-Bat0bq64.js → index-CObinYlG.js} +1 -1
  51. package/dist/client/assets/{index-CdNENSm7.js → index-CQXxVt4A.js} +1 -1
  52. package/dist/client/assets/{index-Bn-vRpKY.js → index-CZ0BaV1t.js} +1 -1
  53. package/dist/client/assets/index-Ca5JlBEc.js +1 -0
  54. package/dist/client/assets/{index-CmQbhXN6.js → index-CfUAagLY.js} +1 -1
  55. package/dist/client/assets/{index-ULWpcSAZ.js → index-CotYqF0w.js} +1 -1
  56. package/dist/client/assets/{index-7AN8MIhq.js → index-CtJTMcuR.js} +1 -1
  57. package/dist/client/assets/{index-nztBriGg.js → index-CtlzkOJ3.js} +3 -3
  58. package/dist/client/assets/{index-9RHYMIP_.js → index-Cvzimc0W.js} +1 -1
  59. package/dist/client/assets/{index-cNE108-h.js → index-D0sn-ct6.js} +1 -1
  60. package/dist/client/assets/{index-BI051zYq.js → index-D1kH8Sr2.js} +2 -2
  61. package/dist/client/assets/{index-DV_54TKu.js → index-DJGEk3-H.js} +1 -1
  62. package/dist/client/assets/{index-B7fRxuTQ.js → index-DQWAoAN-.js} +1 -1
  63. package/dist/client/assets/{index-B4oYDFdX.js → index-DdsOOmtz.js} +1 -1
  64. package/dist/client/assets/{index-CIPmtIuV.js → index-DnN4PJaN.js} +1 -1
  65. package/dist/client/assets/{index-BiqiwP26.js → index-DsH33VjO.js} +4 -4
  66. package/dist/client/assets/{index-ahTVwxpJ.js → index-DwfaFQZo.js} +1 -1
  67. package/dist/client/assets/{index-BuAy0fEx.js → index-Dyeo69l2.js} +1 -1
  68. package/dist/client/assets/{index-E7ZNee_E.js → index-FsBhOkNr.js} +1 -1
  69. package/dist/client/assets/{index-DcwZU98u.js → index-LcH-4hgH.js} +1 -1
  70. package/dist/client/assets/{index-EmzeTf1X.js → index-gHd4-GL-.js} +1 -1
  71. package/dist/client/assets/{index-CFdScmIU.js → index-gIAwAMkn.js} +1 -1
  72. package/dist/client/assets/{room-files-source-CMj0pEdy.js → room-files-source-DRQNpCWs.js} +1 -1
  73. package/dist/client/assets/{soul-file-C_AT0A8U.js → soul-file-DcQD5pcS.js} +1 -1
  74. package/dist/client/assets/{use-personality-commit-ClM-Ahk5.js → use-personality-commit-Dsy9tqWY.js} +1 -1
  75. package/dist/client/index.html +2 -2
  76. package/dist/drizzle/0132_connection_access_levels.sql +84 -0
  77. package/dist/drizzle/0134_query_indexes.sql +8 -0
  78. package/dist/drizzle/0135_session_started_by.sql +13 -0
  79. package/dist/drizzle/meta/0132_snapshot.json +10075 -0
  80. package/dist/drizzle/meta/0134_snapshot.json +10095 -0
  81. package/dist/drizzle/meta/0135_snapshot.json +10176 -0
  82. package/dist/drizzle/meta/_journal.json +22 -1
  83. package/dist/server/index.js +18659 -13468
  84. package/dist/server/index.js.map +2 -2
  85. package/package.json +9 -7
  86. package/dist/client/assets/ConventionPage-fMfStY8d.js +0 -11
  87. package/dist/client/assets/HandlePage-8Gv3fBBC.js +0 -1
  88. package/dist/client/assets/NamePage-CrZUfKVe.js +0 -1
  89. package/dist/client/assets/PhotoPage-C2mHVHvV.js +0 -1
  90. package/dist/client/assets/index-B0qJNUoh.css +0 -1
  91. package/dist/client/assets/index-CtxpF7aO.js +0 -1
  92. package/dist/client/assets/index-N8BCc19i.js +0 -1
package/dist/bin/cli.js CHANGED
@@ -21396,13 +21396,17 @@ function classifyClaudeAccountRows(value, noun = "Claude account") {
21396
21396
  });
21397
21397
  return { rows, warnings };
21398
21398
  }
21399
+ function readProjectRootList(raw) {
21400
+ if (!Array.isArray(raw)) return null;
21401
+ return raw.filter((root) => typeof root === "string" && root.length > 0);
21402
+ }
21399
21403
  function configuredRuntimes(read) {
21400
21404
  const runtimes = ["claude-code"];
21401
21405
  if (read("runtimes.codex.enabled") !== false) runtimes.push("codex");
21402
21406
  if (read("runtimes.opencode.enabled") !== false) runtimes.push("opencode");
21403
21407
  return runtimes;
21404
21408
  }
21405
- var CommunityNavigationRefSchema, ExtensionApprovedSourceSchema, ExtensionDismissedApprovalSchema, CommunityInstallationPathSchema, CommunityInstallationSearchScalarSchema, CommunityInstallationSearchValueSchema, CommunityInstallationDestinationSchema, CommunityNavigationDestinationSchema, CommunityNavigationOwnerPrefsSchema, CommunityNavigationPrefsSchema, ROOM_TURN_LIMIT_BOUNDS, MAX_TOTAL_TURNS_PER_HOUR_BOUNDS, ROOM_TURN_LIMIT_DEFAULTS, MAX_CONCURRENT_TURNS_PER_AGENT_BOUNDS, MAX_CONCURRENT_TURNS_PER_AGENT_DEFAULT, RELAY_TURN_CEILING_BOUNDS, RELAY_TURN_CEILING_DEFAULTS, SENSITIVE_CONFIG_KEYS, CREDENTIAL_REF_PATTERN, CredentialReferenceSchema, ONBOARDING_STEPS, OnboardingStepSchema, OnboardingStateSchema, ToursStateSchema, TOURS_DEFAULTS, DisplayNameSourceSchema, UserProfileSchema, USER_PROFILE_DEFAULTS, SidebarDisplayFilterSchema, SidebarItemRefSchema, SmartGroupRulesSchema, SidebarGroupShapeSchema, SidebarGroupSchema, SidebarSectionIdSchema, SidebarSectionPrefsSchema, SIDEBAR_SECTION_IDS, SidebarSectionsSchema, SidebarPrefsSchema, SIDEBAR_PREFS_DEFAULTS, ShapeUserPrefsSchema, SHAPE_USER_PREFS_DEFAULTS, StatusBarPinSchema, STATUS_BAR_PIN_KEYS, StatusBarPrefsSchema, STATUS_BAR_PREFS_DEFAULTS, ComposerPrefsSchema, COMPOSER_PREFS_DEFAULTS, EscalationDelaySchema, NotificationPrefsSchema, NOTIFICATION_PREFS_DEFAULTS, DEFAULT_AGENTS_DIRECTORY, RawMcpServerConfigSchema, ClaudeCodeAccountSchema, ClaudeCodeAccountsSchema, ClaudeAccountsSeenSchema, CLAUDE_ACCOUNTS_SEEN_KEY, DefaultModelSchema, DefaultEffortSchema, DefaultTrustStopSchema, DefaultAccountColorSchema, ClaudeCodeSettingsSchema, LoggingConfigSchema, PermissionConfigStateSchema, UserConfigSchema, LOG_LEVEL_MAP, USER_CONFIG_DEFAULTS;
21409
+ var CommunityNavigationRefSchema, ExtensionOriginSchema, ExtensionTrustedSourceSchema, ExtensionApprovedSourceSchema, ExtensionDismissedApprovalSchema, CommunityInstallationPathSchema, CommunityInstallationSearchScalarSchema, CommunityInstallationSearchValueSchema, CommunityInstallationDestinationSchema, CommunityNavigationDestinationSchema, CommunityNavigationOwnerPrefsSchema, CommunityNavigationPrefsSchema, ROOM_TURN_LIMIT_BOUNDS, MAX_TOTAL_TURNS_PER_HOUR_BOUNDS, ROOM_TURN_LIMIT_DEFAULTS, MAX_CONCURRENT_TURNS_PER_AGENT_BOUNDS, MAX_CONCURRENT_TURNS_PER_AGENT_DEFAULT, RELAY_TURN_CEILING_BOUNDS, RELAY_TURN_CEILING_DEFAULTS, SENSITIVE_CONFIG_KEYS, CREDENTIAL_REF_PATTERN, CredentialReferenceSchema, ONBOARDING_STEPS, OnboardingStepSchema, OnboardingStateSchema, ToursStateSchema, TOURS_DEFAULTS, DisplayNameSourceSchema, UserProfileSchema, USER_PROFILE_DEFAULTS, SidebarDisplayFilterSchema, SidebarItemRefSchema, SmartGroupRulesSchema, SidebarGroupShapeSchema, SidebarGroupSchema, SidebarSectionIdSchema, SidebarSectionPrefsSchema, SIDEBAR_SECTION_IDS, SidebarSectionsSchema, SidebarPrefsSchema, SIDEBAR_PREFS_DEFAULTS, ShapeUserPrefsSchema, SHAPE_USER_PREFS_DEFAULTS, StatusBarPinSchema, STATUS_BAR_PIN_KEYS, StatusBarPrefsSchema, STATUS_BAR_PREFS_DEFAULTS, ComposerPrefsSchema, COMPOSER_PREFS_DEFAULTS, EscalationDelaySchema, NotificationPrefsSchema, NOTIFICATION_PREFS_DEFAULTS, DEFAULT_AGENTS_DIRECTORY, RawMcpServerConfigSchema, ProjectRootListSchema, TolerantProjectRootListSchema, ProjectAccountsRuleSchema, TolerantProjectAccountsSchema, ClaudeCodeAccountSchema, ClaudeCodeAccountsSchema, ClaudeAccountsSeenSchema, CLAUDE_ACCOUNTS_SEEN_KEY, DefaultModelSchema, DefaultEffortSchema, DefaultTrustStopSchema, DefaultAccountColorSchema, ClaudeCodeSettingsSchema, LoggingConfigSchema, PermissionConfigStateSchema, UserConfigSchema, LOG_LEVEL_MAP, USER_CONFIG_DEFAULTS;
21406
21410
  var init_config_schema = __esm({
21407
21411
  "../shared/src/config-schema.ts"() {
21408
21412
  init_zod();
@@ -21415,6 +21419,18 @@ var init_config_schema = __esm({
21415
21419
  init_permission_ids();
21416
21420
  init_runtime_environment_schema();
21417
21421
  CommunityNavigationRefSchema = external_exports.string().regex(/^[0-9A-Za-z][0-9A-Za-z_-]*$/, "A community ref must be path-safe");
21422
+ ExtensionOriginSchema = external_exports.object({
21423
+ /** The plugin folder that carries the extension. */
21424
+ plugin: external_exports.string().min(1),
21425
+ /** The normalized `owner/repo` the plugin was installed from. */
21426
+ source: external_exports.string().min(1)
21427
+ });
21428
+ ExtensionTrustedSourceSchema = external_exports.object({
21429
+ /** The normalized `owner/repo`, e.g. `dork-labs/marketplace`. */
21430
+ source: external_exports.string().min(1),
21431
+ /** When the person trusted it. ISO 8601. */
21432
+ trustedAt: external_exports.string()
21433
+ });
21418
21434
  ExtensionApprovedSourceSchema = external_exports.object({
21419
21435
  /** Absolute path of the approved extension directory. */
21420
21436
  path: external_exports.string().min(1),
@@ -21422,7 +21438,23 @@ var init_config_schema = __esm({
21422
21438
  * The installed marketplace plugin that carries this extension, when it came
21423
21439
  * inside one; absent for an extension installed directly.
21424
21440
  */
21425
- plugin: external_exports.string().min(1).optional()
21441
+ plugin: external_exports.string().min(1).optional(),
21442
+ /**
21443
+ * Where the approved copy came from, when this machine can prove it (spec
21444
+ * `flow-multiproject` §9.1): the carrying plugin and the `owner/repo` DorkOS's
21445
+ * own installer recorded fetching it from. Present only when the approved
21446
+ * copy had such a trusted origin. Another copy with the same trusted origin
21447
+ * counts as approved too, so the same plugin installed into several projects
21448
+ * asks once. A file inside a project can never supply this: it is read only
21449
+ * from DorkOS's own install records.
21450
+ */
21451
+ origin: ExtensionOriginSchema.optional(),
21452
+ /**
21453
+ * For a copy whose plugin files changed after DorkOS installed it: the
21454
+ * whole plugin folder's digest the person said yes to. Any further change
21455
+ * asks again, because a path alone no longer says what is there.
21456
+ */
21457
+ digest: external_exports.string().min(1).optional()
21426
21458
  });
21427
21459
  ExtensionDismissedApprovalSchema = external_exports.object({
21428
21460
  /** Absolute path of the extension directory the person declined. */
@@ -21864,6 +21896,31 @@ var init_config_schema = __esm({
21864
21896
  /** Streamable HTTP or SSE — the two remote MCP transports. */
21865
21897
  transport: external_exports.enum(["http", "sse"])
21866
21898
  });
21899
+ ProjectRootListSchema = external_exports.array(external_exports.string().min(1));
21900
+ TolerantProjectRootListSchema = external_exports.preprocess(
21901
+ (raw) => readProjectRootList(raw),
21902
+ ProjectRootListSchema.nullable()
21903
+ );
21904
+ ProjectAccountsRuleSchema = external_exports.object({
21905
+ /** The account ids that may work in this project. */
21906
+ allow: external_exports.array(external_exports.string().min(1))
21907
+ });
21908
+ TolerantProjectAccountsSchema = external_exports.preprocess(
21909
+ (raw) => {
21910
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
21911
+ const out = {};
21912
+ for (const [root, rule] of Object.entries(raw)) {
21913
+ if (root.length === 0 || !rule || typeof rule !== "object") continue;
21914
+ const allow = rule.allow;
21915
+ if (!Array.isArray(allow)) continue;
21916
+ out[root] = {
21917
+ allow: allow.filter((id) => typeof id === "string" && id.length > 0)
21918
+ };
21919
+ }
21920
+ return out;
21921
+ },
21922
+ external_exports.record(external_exports.string().min(1), ProjectAccountsRuleSchema)
21923
+ );
21867
21924
  ClaudeCodeAccountSchema = external_exports.object({
21868
21925
  /**
21869
21926
  * Stable kebab-case slug for this account, unique within the registry. What
@@ -21882,7 +21939,21 @@ var init_config_schema = __esm({
21882
21939
  * color follows the palette if it changes. A value that is not lowercase
21883
21940
  * `#rrggbb` reads as `null` rather than failing the whole config.
21884
21941
  */
21885
- color: external_exports.string().regex(ACCOUNT_COLOR_PATTERN).nullable().default(null).catch(null)
21942
+ color: external_exports.string().regex(ACCOUNT_COLOR_PATTERN).nullable().default(null).catch(null),
21943
+ /**
21944
+ * The projects this account may work in, as canonical project roots (git
21945
+ * main checkouts), or `null` for any project (spec `flow-multiproject` §8,
21946
+ * N6). A list never includes "no project": an account kept to client-app
21947
+ * does not run in a folder that is in no repository. Written only by a
21948
+ * person, through `PUT /api/runtimes/claude-code/accounts/:id/only-projects`.
21949
+ *
21950
+ * Optional rather than defaulted, and absent reads exactly as `null`: a row
21951
+ * is a shared contract with flow (readers ignore fields they do not know,
21952
+ * writers keep them), so rows written by an older flow or by hand carry no
21953
+ * such field, and every reader (`readProjectRootList`) treats that as "any
21954
+ * project". The `'0.93.0'` migration still writes `null` onto stored rows.
21955
+ */
21956
+ onlyProjects: TolerantProjectRootListSchema.optional()
21886
21957
  });
21887
21958
  ClaudeCodeAccountsSchema = external_exports.preprocess(
21888
21959
  backfillMissingAccountIds,
@@ -21949,6 +22020,22 @@ var init_config_schema = __esm({
21949
22020
  * folder: that row's own color wins. See {@link DefaultAccountColorSchema}.
21950
22021
  */
21951
22022
  defaultAccountColor: DefaultAccountColorSchema.default(null).catch(null),
22023
+ /**
22024
+ * The projects Main (this computer's own sign-in, id `default`) may work in,
22025
+ * as canonical project roots, or `null` for any project. Main has no
22026
+ * registry row to carry `onlyProjects`, so its rule lives here, the same
22027
+ * pattern as `defaultAccountColor` (spec `flow-multiproject` §8.1).
22028
+ */
22029
+ defaultAccountOnlyProjects: TolerantProjectRootListSchema.default(null),
22030
+ /**
22031
+ * Per-project account rules, keyed by canonical project root: which
22032
+ * accounts may work in that project (spec `flow-multiproject` §8.1, N6). A
22033
+ * project with no entry allows every account. An account works in a project
22034
+ * only when both its own rule and the project's allow it. Written only by a
22035
+ * person, through `PUT /api/runtimes/claude-code/project-accounts`, which
22036
+ * rewrites the whole object: the keys are paths and contain dots.
22037
+ */
22038
+ projectAccounts: TolerantProjectAccountsSchema.default({}),
21952
22039
  /**
21953
22040
  * Account folders a person dismissed from Settings' "Found on this
21954
22041
  * computer" list, so they stay hidden across restarts (spec
@@ -22743,13 +22830,24 @@ var init_config_schema = __esm({
22743
22830
  * to a consent question, and an agent that could write it could hide the
22744
22831
  * question from them.
22745
22832
  */
22746
- dismissedApprovals: external_exports.record(external_exports.string(), ExtensionDismissedApprovalSchema).default(() => ({}))
22833
+ dismissedApprovals: external_exports.record(external_exports.string(), ExtensionDismissedApprovalSchema).default(() => ({})),
22834
+ /**
22835
+ * The code sources a person trusts (spec `flow-multiproject` §9.3): an
22836
+ * extension whose copy provably came from one of these runs without an
22837
+ * approval row. Keyed on a trusted origin's `owner/repo`, so a clone
22838
+ * that merely claims a source is never covered.
22839
+ *
22840
+ * `operator-only`: it decides which code runs. Trusting a new source is
22841
+ * one of the three asks only a person can answer.
22842
+ */
22843
+ trustedSources: external_exports.array(ExtensionTrustedSourceSchema).default(() => [])
22747
22844
  }).default(() => ({
22748
22845
  enabled: [],
22749
22846
  disabled: [],
22750
22847
  approvedToRun: [],
22751
22848
  approvedSources: {},
22752
- dismissedApprovals: {}
22849
+ dismissedApprovals: {},
22850
+ trustedSources: []
22753
22851
  })),
22754
22852
  mcp: external_exports.object({
22755
22853
  enabled: external_exports.boolean().default(true),
@@ -23045,6 +23143,8 @@ var init_config_schema = __esm({
23045
23143
  defaultAccount: null,
23046
23144
  accounts: [],
23047
23145
  defaultAccountColor: null,
23146
+ defaultAccountOnlyProjects: null,
23147
+ projectAccounts: {},
23048
23148
  dismissedFolders: [],
23049
23149
  defaultModel: null,
23050
23150
  defaultEffort: null,
@@ -23128,6 +23228,8 @@ var init_config_schema = __esm({
23128
23228
  defaultAccount: null,
23129
23229
  accounts: [],
23130
23230
  defaultAccountColor: null,
23231
+ defaultAccountOnlyProjects: null,
23232
+ projectAccounts: {},
23131
23233
  dismissedFolders: [],
23132
23234
  defaultModel: null,
23133
23235
  defaultEffort: null,
@@ -25488,6 +25590,7 @@ function logError(err) {
25488
25590
  var DEFAULT_MAX_LOG_SIZE, DEFAULT_MAX_LOG_FILES, logDir, logFile, maxLogSize, maxLogFiles, configuredLevel, TAG_PREFIX_PATTERN, logger;
25489
25591
  var init_logger = __esm({
25490
25592
  "../../apps/server/src/lib/logger.ts"() {
25593
+ "use strict";
25491
25594
  init_dist();
25492
25595
  init_dispatch_context();
25493
25596
  init_serialize_error();
@@ -25808,7 +25911,7 @@ import path2 from "path";
25808
25911
  import { fileURLToPath } from "url";
25809
25912
  function resolveVersion() {
25810
25913
  if (env2.DORKOS_VERSION_OVERRIDE) return env2.DORKOS_VERSION_OVERRIDE;
25811
- if (true) return "0.92.0";
25914
+ if (true) return "0.93.0";
25812
25915
  const pkgPath = path2.join(path2.dirname(fileURLToPath(import.meta.url)), "../../package.json");
25813
25916
  return JSON.parse(readFileSync(pkgPath, "utf-8")).version;
25814
25917
  }
@@ -25894,6 +25997,18 @@ function moreProtective(entry, stored, fresh) {
25894
25997
  if (typeof fresh !== "number") return void 0;
25895
25998
  return stored > fresh ? stored : void 0;
25896
25999
  }
26000
+ case "ruled": {
26001
+ if (Array.isArray(stored)) {
26002
+ if (fresh !== null || !stored.every((item) => typeof item === "string")) return void 0;
26003
+ return stored;
26004
+ }
26005
+ if (stored === null || typeof stored !== "object") return void 0;
26006
+ if (Object.keys(stored).length === 0) return void 0;
26007
+ if (fresh === null || typeof fresh !== "object" || Object.keys(fresh).length > 0) {
26008
+ return void 0;
26009
+ }
26010
+ return stored;
26011
+ }
25897
26012
  case "restricted": {
25898
26013
  if (!Array.isArray(stored) || !stored.every((item) => typeof item === "string")) {
25899
26014
  return void 0;
@@ -25939,8 +26054,8 @@ function applyProtectedState(store, salvaged) {
25939
26054
  const section = (name) => {
25940
26055
  const existing = sections.get(name);
25941
26056
  if (existing) return existing;
25942
- const current = store.get(name);
25943
- const draft = current !== null && typeof current === "object" ? { ...current } : {};
26057
+ const current2 = store.get(name);
26058
+ const draft = current2 !== null && typeof current2 === "object" ? { ...current2 } : {};
25944
26059
  sections.set(name, draft);
25945
26060
  return draft;
25946
26061
  };
@@ -26154,6 +26269,22 @@ var init_protected_state = __esm({
26154
26269
  protectiveValue: false,
26155
26270
  reason: "Warm agents default ON (spec `full-power-defaults`). Holding a process open between messages costs memory \u2014 up to about 1 GB per warm agent \u2014 so somebody who turned it off did so to get that memory back, on a machine that presumably needed it. A wipe that handed the default back would take it away again with nothing on screen to say why."
26156
26271
  },
26272
+ {
26273
+ path: "runtimes.claudeCode.defaultAccountOnlyProjects",
26274
+ direction: "ruled",
26275
+ reason: 'Main (this computer\'s own Claude sign-in) kept to some projects (spec `flow-multiproject` \xA78). The default is any project, so a wipe that forgot "Main is only for client-app" would silently let it work in personal repos: the DOR-584 class of loss.'
26276
+ },
26277
+ {
26278
+ path: "runtimes.claudeCode.projectAccounts",
26279
+ direction: "ruled",
26280
+ reason: "Which accounts each project may use (spec `flow-multiproject` \xA78). The default is no limits, so a wipe that forgot a project's list would let every account work there again, including one the person kept out on purpose."
26281
+ },
26282
+ // `runtimes.claudeCode.accounts[].onlyProjects` has no entry, on purpose: a
26283
+ // wipe does not carry the account registry itself (no row, no path), so the
26284
+ // account it limited is no longer one DorkOS can launch on. There is nothing
26285
+ // for the rule to protect until the person registers the account again, and
26286
+ // a row cannot be carried by one leaf without its folder and id. Pinned by
26287
+ // `protected-state.test.ts`.
26157
26288
  {
26158
26289
  path: "scheduler.maxConcurrentRuns",
26159
26290
  direction: "lower",
@@ -26321,24 +26452,24 @@ function leafStub(node2) {
26321
26452
  return stub;
26322
26453
  }
26323
26454
  function objectShape(schema3) {
26324
- let current = schema3;
26455
+ let current2 = schema3;
26325
26456
  for (let depth = 0; depth < MAX_ZOD_WRAPPERS; depth++) {
26326
- const def = current.def;
26457
+ const def = current2.def;
26327
26458
  if (def.type === "object" && def.shape !== void 0) return def.shape;
26328
26459
  if (def.innerType === void 0) return void 0;
26329
- current = def.innerType;
26460
+ current2 = def.innerType;
26330
26461
  }
26331
26462
  return void 0;
26332
26463
  }
26333
26464
  function resolveLeafSchema(segments) {
26334
- let current = UserConfigSchema;
26465
+ let current2 = UserConfigSchema;
26335
26466
  for (const segment of segments) {
26336
- const shape = objectShape(current);
26467
+ const shape = objectShape(current2);
26337
26468
  const next = shape?.[segment];
26338
26469
  if (next === void 0) return void 0;
26339
- current = next;
26470
+ current2 = next;
26340
26471
  }
26341
- return current;
26472
+ return current2;
26342
26473
  }
26343
26474
  function relaxIn(properties, segments, leaves) {
26344
26475
  for (const [key, child] of Object.entries(properties)) {
@@ -26514,12 +26645,14 @@ __export(config_manager_exports, {
26514
26645
  retireToolOnlyReplies: () => retireToolOnlyReplies,
26515
26646
  scrubRetiredOnboardingSteps: () => scrubRetiredOnboardingSteps,
26516
26647
  seedA2aDisabled: () => seedA2aDisabled,
26648
+ seedAccountProjectRules: () => seedAccountProjectRules,
26517
26649
  seedClaudeDismissedFolders: () => seedClaudeDismissedFolders,
26518
26650
  seedCommunityNavigationPrefs: () => seedCommunityNavigationPrefs,
26519
26651
  seedDefaultAccountColor: () => seedDefaultAccountColor,
26520
26652
  seedDisplayNameSourceDefault: () => seedDisplayNameSourceDefault,
26521
26653
  seedExtensionsApprovedSources: () => seedExtensionsApprovedSources,
26522
26654
  seedExtensionsDismissedApprovals: () => seedExtensionsDismissedApprovals,
26655
+ seedExtensionsTrustedSources: () => seedExtensionsTrustedSources,
26523
26656
  seedFullPowerDecision: () => seedFullPowerDecision,
26524
26657
  seedHarnessAutoAdopt: () => seedHarnessAutoAdopt,
26525
26658
  seedHarnessGlobal: () => seedHarnessGlobal,
@@ -26702,6 +26835,12 @@ function seedExtensionsDismissedApprovals(store) {
26702
26835
  if (dismissed && typeof dismissed === "object" && !Array.isArray(dismissed)) return;
26703
26836
  store.set("extensions", { ...ext, dismissedApprovals: {} });
26704
26837
  }
26838
+ function seedExtensionsTrustedSources(store) {
26839
+ const ext = store.get("extensions");
26840
+ if (!ext || typeof ext !== "object" || Array.isArray(ext)) return;
26841
+ if (Array.isArray(ext.trustedSources)) return;
26842
+ store.set("extensions", { ...ext, trustedSources: [] });
26843
+ }
26705
26844
  function backfillWorkspaceDefaults(store) {
26706
26845
  if (store.get("workspace") == null) {
26707
26846
  store.set("workspace", {
@@ -27023,27 +27162,27 @@ function backfillRoomsDefaults(store) {
27023
27162
  store.set("rooms", seeded);
27024
27163
  return;
27025
27164
  }
27026
- const current = { ...rooms2 };
27165
+ const current2 = { ...rooms2 };
27027
27166
  let changed = false;
27028
27167
  for (const [key, value] of Object.entries(seeded)) {
27029
- if (current[key] === void 0) {
27030
- current[key] = value;
27168
+ if (current2[key] === void 0) {
27169
+ current2[key] = value;
27031
27170
  changed = true;
27032
27171
  }
27033
27172
  }
27034
- if (current.maxAutomaticTurnsPerHour !== void 0) {
27035
- if (typeof current.maxAutomaticTurnsPerHour === "number") {
27036
- current.maxAutomaticTurnsPerRoomPerHour = current.maxAutomaticTurnsPerHour;
27173
+ if (current2.maxAutomaticTurnsPerHour !== void 0) {
27174
+ if (typeof current2.maxAutomaticTurnsPerHour === "number") {
27175
+ current2.maxAutomaticTurnsPerRoomPerHour = current2.maxAutomaticTurnsPerHour;
27037
27176
  }
27038
- delete current.maxAutomaticTurnsPerHour;
27177
+ delete current2.maxAutomaticTurnsPerHour;
27039
27178
  changed = true;
27040
27179
  }
27041
- if (changed) store.set("rooms", current);
27180
+ if (changed) store.set("rooms", current2);
27042
27181
  }
27043
27182
  function raiseRoomTurnLimits(store) {
27044
27183
  const rooms2 = store.get("rooms");
27045
27184
  if (rooms2 == null || typeof rooms2 !== "object") return;
27046
- const current = { ...rooms2 };
27185
+ const current2 = { ...rooms2 };
27047
27186
  let changed = false;
27048
27187
  const RAISED = [
27049
27188
  ["maxAgentDepth", 3, 30],
@@ -27051,8 +27190,8 @@ function raiseRoomTurnLimits(store) {
27051
27190
  ["maxAutomaticTurnsTotalPerHour", 240, 5e3]
27052
27191
  ];
27053
27192
  for (const [key, was, becomes] of RAISED) {
27054
- if (current[key] === was) {
27055
- current[key] = becomes;
27193
+ if (current2[key] === was) {
27194
+ current2[key] = becomes;
27056
27195
  changed = true;
27057
27196
  }
27058
27197
  }
@@ -27061,12 +27200,12 @@ function raiseRoomTurnLimits(store) {
27061
27200
  maxTurnsPerAgentPerCascade: 10
27062
27201
  };
27063
27202
  for (const [key, value] of Object.entries(ADDED)) {
27064
- if (current[key] === void 0) {
27065
- current[key] = value;
27203
+ if (current2[key] === void 0) {
27204
+ current2[key] = value;
27066
27205
  changed = true;
27067
27206
  }
27068
27207
  }
27069
- if (changed) store.set("rooms", current);
27208
+ if (changed) store.set("rooms", current2);
27070
27209
  }
27071
27210
  function backfillWelcomeBackDefaults(store) {
27072
27211
  const seeded = {
@@ -27080,15 +27219,15 @@ function backfillWelcomeBackDefaults(store) {
27080
27219
  store.set("welcomeBack", seeded);
27081
27220
  return;
27082
27221
  }
27083
- const current = { ...stored };
27222
+ const current2 = { ...stored };
27084
27223
  let changed = false;
27085
27224
  for (const [key, value] of Object.entries(seeded)) {
27086
- if (current[key] === void 0) {
27087
- current[key] = value;
27225
+ if (current2[key] === void 0) {
27226
+ current2[key] = value;
27088
27227
  changed = true;
27089
27228
  }
27090
27229
  }
27091
- if (changed) store.set("welcomeBack", current);
27230
+ if (changed) store.set("welcomeBack", current2);
27092
27231
  }
27093
27232
  function backfillSmartGroupKindDefaults(store) {
27094
27233
  const ui = store.get("ui");
@@ -27223,9 +27362,9 @@ function backfillClaudeCodeRuntimeDefaults(store) {
27223
27362
  function backfillRuntimeExecutionDefaults(store) {
27224
27363
  const runtimes = store.get("runtimes");
27225
27364
  if (runtimes == null || typeof runtimes !== "object") return;
27226
- const current = runtimes;
27365
+ const current2 = runtimes;
27227
27366
  const seed = (section, leaves) => {
27228
- const value = current[section];
27367
+ const value = current2[section];
27229
27368
  if (value == null || typeof value !== "object") return null;
27230
27369
  const block = value;
27231
27370
  const missing = leaves.filter((leaf) => !(leaf in block));
@@ -27237,7 +27376,7 @@ function backfillRuntimeExecutionDefaults(store) {
27237
27376
  const opencode = seed("opencode", ["defaultModel"]);
27238
27377
  if (!claudeCode && !codex && !opencode) return;
27239
27378
  store.set("runtimes", {
27240
- ...current,
27379
+ ...current2,
27241
27380
  ...claudeCode ? { claudeCode } : {},
27242
27381
  ...codex ? { codex } : {},
27243
27382
  ...opencode ? { opencode } : {}
@@ -27246,9 +27385,9 @@ function backfillRuntimeExecutionDefaults(store) {
27246
27385
  function backfillDefaultTrustStops(store) {
27247
27386
  const runtimes = store.get("runtimes");
27248
27387
  if (runtimes == null || typeof runtimes !== "object") return;
27249
- const current = runtimes;
27388
+ const current2 = runtimes;
27250
27389
  const seed = (section) => {
27251
- const value = current[section];
27390
+ const value = current2[section];
27252
27391
  if (value == null || typeof value !== "object") return null;
27253
27392
  const block = value;
27254
27393
  if ("defaultTrustStop" in block) return null;
@@ -27257,10 +27396,10 @@ function backfillDefaultTrustStops(store) {
27257
27396
  const claudeCode = seed("claudeCode");
27258
27397
  const codex = seed("codex");
27259
27398
  const opencode = seed("opencode");
27260
- const global2 = "defaultTrustStop" in current ? null : { defaultTrustStop: null };
27399
+ const global2 = "defaultTrustStop" in current2 ? null : { defaultTrustStop: null };
27261
27400
  if (!claudeCode && !codex && !opencode && !global2) return;
27262
27401
  store.set("runtimes", {
27263
- ...current,
27402
+ ...current2,
27264
27403
  ...global2 ?? {},
27265
27404
  ...claudeCode ? { claudeCode } : {},
27266
27405
  ...codex ? { codex } : {},
@@ -27270,19 +27409,19 @@ function backfillDefaultTrustStops(store) {
27270
27409
  function backfillClaudeCodePersistentSession(store) {
27271
27410
  const runtimes = store.get("runtimes");
27272
27411
  if (runtimes == null || typeof runtimes !== "object") return;
27273
- const current = runtimes;
27274
- const claudeCode = current.claudeCode;
27412
+ const current2 = runtimes;
27413
+ const claudeCode = current2.claudeCode;
27275
27414
  if (claudeCode == null || typeof claudeCode !== "object") return;
27276
27415
  const block = claudeCode;
27277
27416
  if ("persistentSession" in block) return;
27278
27417
  store.set("runtimes", {
27279
- ...current,
27418
+ ...current2,
27280
27419
  claudeCode: { ...block, persistentSession: false }
27281
27420
  });
27282
27421
  }
27283
27422
  function seedA2aDisabled(store) {
27284
- const current = store.get("a2a");
27285
- if (current != null && typeof current === "object") return;
27423
+ const current2 = store.get("a2a");
27424
+ if (current2 != null && typeof current2 === "object") return;
27286
27425
  store.set("a2a", { enabled: false });
27287
27426
  }
27288
27427
  function backfillPromoDismissals(store) {
@@ -27376,6 +27515,39 @@ function seedDefaultAccountColor(store) {
27376
27515
  claudeCode: { ...block, defaultAccountColor: null }
27377
27516
  });
27378
27517
  }
27518
+ function seedAccountProjectRules(store) {
27519
+ const runtimes = store.get("runtimes");
27520
+ if (!runtimes || typeof runtimes !== "object" || Array.isArray(runtimes)) return;
27521
+ const block = runtimes.claudeCode;
27522
+ if (!block || typeof block !== "object" || Array.isArray(block)) return;
27523
+ const current2 = block;
27524
+ const next = { ...current2 };
27525
+ let changed = false;
27526
+ if (!("projectAccounts" in current2)) {
27527
+ next.projectAccounts = {};
27528
+ changed = true;
27529
+ }
27530
+ if (!("defaultAccountOnlyProjects" in current2)) {
27531
+ next.defaultAccountOnlyProjects = null;
27532
+ changed = true;
27533
+ }
27534
+ if (Array.isArray(current2.accounts)) {
27535
+ let rowsChanged = false;
27536
+ const rows = current2.accounts.map((row) => {
27537
+ if (!row || typeof row !== "object" || Array.isArray(row) || "onlyProjects" in row) {
27538
+ return row;
27539
+ }
27540
+ rowsChanged = true;
27541
+ return { ...row, onlyProjects: null };
27542
+ });
27543
+ if (rowsChanged) {
27544
+ next.accounts = rows;
27545
+ changed = true;
27546
+ }
27547
+ }
27548
+ if (!changed) return;
27549
+ store.set("runtimes", { ...runtimes, claudeCode: next });
27550
+ }
27379
27551
  function seedClaudeDismissedFolders(store) {
27380
27552
  const runtimes = store.get("runtimes");
27381
27553
  if (!runtimes || typeof runtimes !== "object" || Array.isArray(runtimes)) return;
@@ -27413,13 +27585,13 @@ function raiseSchedulerConcurrencyFloor(store) {
27413
27585
  function warmClaudeCodeSessionsByDefault(store) {
27414
27586
  const runtimes = store.get("runtimes");
27415
27587
  if (runtimes == null || typeof runtimes !== "object") return;
27416
- const current = runtimes;
27417
- const claudeCode = current.claudeCode;
27588
+ const current2 = runtimes;
27589
+ const claudeCode = current2.claudeCode;
27418
27590
  if (claudeCode == null || typeof claudeCode !== "object") return;
27419
27591
  const block = claudeCode;
27420
27592
  if (block.persistentSession !== false) return;
27421
27593
  store.set("runtimes", {
27422
- ...current,
27594
+ ...current2,
27423
27595
  claudeCode: { ...block, persistentSession: true }
27424
27596
  });
27425
27597
  }
@@ -27430,26 +27602,26 @@ function seedMemoryProviderDefault(store) {
27430
27602
  function seedRoomRepoDefaults(store) {
27431
27603
  const rooms2 = store.get("rooms");
27432
27604
  if (rooms2 == null || typeof rooms2 !== "object") return;
27433
- const current = rooms2;
27434
- if (current.repo != null) return;
27435
- store.set("rooms", { ...current, repo: USER_CONFIG_DEFAULTS.rooms.repo });
27605
+ const current2 = rooms2;
27606
+ if (current2.repo != null) return;
27607
+ store.set("rooms", { ...current2, repo: USER_CONFIG_DEFAULTS.rooms.repo });
27436
27608
  }
27437
27609
  function dropRetiredDorkosTools(store) {
27438
27610
  const runtimes = store.get("runtimes");
27439
27611
  if (runtimes == null || typeof runtimes !== "object") return;
27440
- const current = runtimes;
27441
- if (!("dorkosTools" in current)) return;
27442
- const { dorkosTools: _retired, ...rest } = current;
27612
+ const current2 = runtimes;
27613
+ if (!("dorkosTools" in current2)) return;
27614
+ const { dorkosTools: _retired, ...rest } = current2;
27443
27615
  store.set("runtimes", rest);
27444
27616
  }
27445
27617
  function retireToolOnlyReplies(store) {
27446
27618
  const rooms2 = store.get("rooms");
27447
27619
  if (rooms2 == null || typeof rooms2 !== "object") return;
27448
- const current = rooms2;
27449
- const { toolOnlyReplies: _retired, ...rest } = current;
27620
+ const current2 = rooms2;
27621
+ const { toolOnlyReplies: _retired, ...rest } = current2;
27450
27622
  const next = { ...rest };
27451
- let changed = "toolOnlyReplies" in current;
27452
- if (current.maxPostsPerTurn == null) {
27623
+ let changed = "toolOnlyReplies" in current2;
27624
+ if (current2.maxPostsPerTurn == null) {
27453
27625
  next.maxPostsPerTurn = USER_CONFIG_DEFAULTS.rooms.maxPostsPerTurn;
27454
27626
  changed = true;
27455
27627
  }
@@ -27459,61 +27631,61 @@ function retireToolOnlyReplies(store) {
27459
27631
  function seedDisplayNameSourceDefault(store) {
27460
27632
  const profile = store.get("profile");
27461
27633
  if (profile == null || typeof profile !== "object") return;
27462
- const current = profile;
27463
- if ("displayNameSource" in current) return;
27634
+ const current2 = profile;
27635
+ if ("displayNameSource" in current2) return;
27464
27636
  store.set("profile", {
27465
- ...current,
27637
+ ...current2,
27466
27638
  displayNameSource: USER_CONFIG_DEFAULTS.profile.displayNameSource
27467
27639
  });
27468
27640
  }
27469
27641
  function seedIdentityPromptDismissedDefault(store) {
27470
27642
  const profile = store.get("profile");
27471
27643
  if (profile == null || typeof profile !== "object") return;
27472
- const current = profile;
27473
- if ("identityPromptDismissedAt" in current) return;
27644
+ const current2 = profile;
27645
+ if ("identityPromptDismissedAt" in current2) return;
27474
27646
  store.set("profile", {
27475
- ...current,
27647
+ ...current2,
27476
27648
  identityPromptDismissedAt: USER_CONFIG_DEFAULTS.profile.identityPromptDismissedAt
27477
27649
  });
27478
27650
  }
27479
27651
  function seedHarnessRefusedHooks(store) {
27480
27652
  const harness = store.get("harness");
27481
27653
  if (harness == null || typeof harness !== "object") return;
27482
- const current = harness;
27483
- if (Array.isArray(current.refusedHooks)) return;
27484
- store.set("harness", { ...current, refusedHooks: [] });
27654
+ const current2 = harness;
27655
+ if (Array.isArray(current2.refusedHooks)) return;
27656
+ store.set("harness", { ...current2, refusedHooks: [] });
27485
27657
  }
27486
27658
  function seedHarnessGlobal(store) {
27487
27659
  const harness = store.get("harness");
27488
27660
  if (harness == null || typeof harness !== "object") return;
27489
- const current = harness;
27490
- if (current.global != null && typeof current.global === "object") return;
27491
- store.set("harness", { ...current, global: { harnesses: [], askedAt: null } });
27661
+ const current2 = harness;
27662
+ if (current2.global != null && typeof current2.global === "object") return;
27663
+ store.set("harness", { ...current2, global: { harnesses: [], askedAt: null } });
27492
27664
  }
27493
27665
  function seedHarnessAutoAdopt(store) {
27494
27666
  const harness = store.get("harness");
27495
27667
  if (harness == null || typeof harness !== "object") return;
27496
- const current = harness;
27497
- if (typeof current.autoAdopt === "boolean") return;
27498
- store.set("harness", { ...current, autoAdopt: false });
27668
+ const current2 = harness;
27669
+ if (typeof current2.autoAdopt === "boolean") return;
27670
+ store.set("harness", { ...current2, autoAdopt: false });
27499
27671
  }
27500
27672
  function seedRoomCanvasOps(store) {
27501
27673
  const rooms2 = store.get("rooms");
27502
27674
  if (rooms2 == null || typeof rooms2 !== "object") return;
27503
- const current = rooms2;
27504
- if (current.maxCanvasOpsPerTurn != null) return;
27675
+ const current2 = rooms2;
27676
+ if (current2.maxCanvasOpsPerTurn != null) return;
27505
27677
  store.set("rooms", {
27506
- ...current,
27678
+ ...current2,
27507
27679
  maxCanvasOpsPerTurn: USER_CONFIG_DEFAULTS.rooms.maxCanvasOpsPerTurn
27508
27680
  });
27509
27681
  }
27510
27682
  function seedMaxConcurrentTurnsPerAgent(store) {
27511
27683
  const rooms2 = store.get("rooms");
27512
27684
  if (rooms2 == null || typeof rooms2 !== "object") return;
27513
- const current = rooms2;
27514
- if (current.maxConcurrentTurnsPerAgent != null) return;
27685
+ const current2 = rooms2;
27686
+ if (current2.maxConcurrentTurnsPerAgent != null) return;
27515
27687
  store.set("rooms", {
27516
- ...current,
27688
+ ...current2,
27517
27689
  maxConcurrentTurnsPerAgent: USER_CONFIG_DEFAULTS.rooms.maxConcurrentTurnsPerAgent
27518
27690
  });
27519
27691
  }
@@ -27561,8 +27733,8 @@ function retireAgentContextSettings(store) {
27561
27733
  const blocked = [];
27562
27734
  if (off.length > 0) {
27563
27735
  const permissions = store.get("permissions");
27564
- const current = permissions && typeof permissions === "object" && !Array.isArray(permissions) ? permissions : { preset: null, defaults: { areas: {}, actions: {} }, upgradeSweptVersion: null };
27565
- const defaults = current.defaults && typeof current.defaults === "object" && !Array.isArray(current.defaults) ? current.defaults : { areas: {}, actions: {} };
27736
+ const current2 = permissions && typeof permissions === "object" && !Array.isArray(permissions) ? permissions : { preset: null, defaults: { areas: {}, actions: {} }, upgradeSweptVersion: null };
27737
+ const defaults = current2.defaults && typeof current2.defaults === "object" && !Array.isArray(current2.defaults) ? current2.defaults : { areas: {}, actions: {} };
27566
27738
  const areas = {
27567
27739
  ...defaults.areas ?? {}
27568
27740
  };
@@ -27573,7 +27745,7 @@ function retireAgentContextSettings(store) {
27573
27745
  }
27574
27746
  if (blocked.length > 0) {
27575
27747
  store.set("permissions", {
27576
- ...current,
27748
+ ...current2,
27577
27749
  defaults: { actions: {}, ...defaults, areas }
27578
27750
  });
27579
27751
  }
@@ -27618,6 +27790,8 @@ function tolerateLegacyClaudeAccountEncoding(ctx) {
27618
27790
  anyOf: [{ type: "string" }, { type: "null" }],
27619
27791
  default: null
27620
27792
  };
27793
+ properties.defaultAccountOnlyProjects = { default: null };
27794
+ properties.projectAccounts = { default: {} };
27621
27795
  return;
27622
27796
  }
27623
27797
  if (ctx.zodSchema !== ClaudeCodeAccountSchema) return;
@@ -28097,10 +28271,10 @@ and your settings stay in the file you renamed.`;
28097
28271
  },
28098
28272
  // New nested defaults only; historical migration bodies stay immutable.
28099
28273
  "0.76.0": (store) => {
28100
- const current = store.get("runtimes");
28274
+ const current2 = store.get("runtimes");
28101
28275
  store.set("runtimes", {
28102
- ...current,
28103
- environment: current?.environment ?? { inherit: { claudeCode: [], codex: [], opencode: [] } }
28276
+ ...current2,
28277
+ environment: current2?.environment ?? { inherit: { claudeCode: [], codex: [], opencode: [] } }
28104
28278
  });
28105
28279
  },
28106
28280
  // 0.76.0 has merged (DOR-1903, a `runtimes` leaf) and 0.74.0 is the newest
@@ -28261,6 +28435,29 @@ and your settings stay in the file you renamed.`;
28261
28435
  // body preserves.
28262
28436
  "0.92.0": (store) => {
28263
28437
  seedExtensionsDismissedApprovals(store);
28438
+ },
28439
+ // 0.92.0 has merged (DOR-2517, extension approvals a person said "Not now"
28440
+ // to), so 0.93.0 is the next key. Frozen from merge, not from the release
28441
+ // bump, for the reason `'0.60.0'` above states; anything further opens
28442
+ // `'0.94.0'`.
28443
+ //
28444
+ // Disjoint from every other key here: it adds two nested leaves under
28445
+ // `runtimes.claudeCode` and one leaf on each `accounts[]` row, none of which
28446
+ // anything above names, and keeps every member `'0.65.0'`, `'0.87.0'`,
28447
+ // `'0.90.0'` and `'0.91.0'` write there.
28448
+ "0.93.0": (store) => {
28449
+ seedAccountProjectRules(store);
28450
+ },
28451
+ // 0.93.0 has merged (DOR-2526, account project rules) and v0.89.0 is the
28452
+ // newest tag, so 0.94.0 is the next key. Frozen from merge, not from the
28453
+ // release bump, for the reason `'0.60.0'` above states; anything further
28454
+ // opens `'0.95.0'`.
28455
+ //
28456
+ // Disjoint from every other key here: it adds one nested leaf under
28457
+ // `extensions`, beside `dismissedApprovals`, which `'0.92.0'` writes and this
28458
+ // body preserves.
28459
+ "0.94.0": (store) => {
28460
+ seedExtensionsTrustedSources(store);
28264
28461
  }
28265
28462
  };
28266
28463
  jsonSchemaFull = external_exports.toJSONSchema(UserConfigSchema, {
@@ -30396,11 +30593,11 @@ var init_env2 = __esm({
30396
30593
  // src/startup-diagnostics.ts
30397
30594
  import os2 from "os";
30398
30595
  function checkNodeVersion(version4 = process.versions.node) {
30399
- const current = version4.split(".").map((part) => Number.parseInt(part, 10));
30596
+ const current2 = version4.split(".").map((part) => Number.parseInt(part, 10));
30400
30597
  const minimum = MIN_NODE_VERSION.split(".").map((part) => Number.parseInt(part, 10));
30401
30598
  const supported2 = minimum.every((minimumPart, index2) => {
30402
- const currentPart = current[index2] ?? 0;
30403
- const equalPrefix = minimum.slice(0, index2).every((part, prior) => part === current[prior]);
30599
+ const currentPart = current2[index2] ?? 0;
30600
+ const equalPrefix = minimum.slice(0, index2).every((part, prior) => part === current2[prior]);
30404
30601
  return !equalPrefix || currentPart >= minimumPart;
30405
30602
  });
30406
30603
  if (!supported2) {
@@ -30638,6 +30835,7 @@ function requiresClaudePlugin(type2) {
30638
30835
  var PackageTypeSchema;
30639
30836
  var init_package_types = __esm({
30640
30837
  "../marketplace/src/package-types.ts"() {
30838
+ "use strict";
30641
30839
  init_zod();
30642
30840
  PackageTypeSchema = external_exports.enum(["agent", "plugin", "skill-pack", "adapter", "shape"]);
30643
30841
  }
@@ -32384,15 +32582,15 @@ async function readPackageFileWithin(root, relPath2, maxBytes, what) {
32384
32582
  `${what} is reached through a symbolic link, which DorkOS does not follow inside a package.`
32385
32583
  );
32386
32584
  const parts = inside.split(path11.sep);
32387
- let current = root;
32585
+ let current2 = root;
32388
32586
  for (const part of parts) {
32389
- current = path11.join(current, part);
32390
- if ((await lstat(current)).isSymbolicLink()) throw linked();
32587
+ current2 = path11.join(current2, part);
32588
+ if ((await lstat(current2)).isSymbolicLink()) throw linked();
32391
32589
  }
32392
32590
  await readPackageFileHooks.beforeOpen?.();
32393
32591
  let handle;
32394
32592
  try {
32395
- handle = await open2(current, readNoFollowFlags());
32593
+ handle = await open2(current2, readNoFollowFlags());
32396
32594
  } catch (err) {
32397
32595
  if (err.code === "ELOOP") throw linked();
32398
32596
  throw err;
@@ -32401,9 +32599,9 @@ async function readPackageFileWithin(root, relPath2, maxBytes, what) {
32401
32599
  await readPackageFileHooks.afterOpen?.();
32402
32600
  const [opened, atPath, realRoot, realFile] = await Promise.all([
32403
32601
  handle.stat(),
32404
- lstat(current),
32602
+ lstat(current2),
32405
32603
  realpath(root),
32406
- realpath(current)
32604
+ realpath(current2)
32407
32605
  ]);
32408
32606
  const fromRoot = path11.relative(realRoot, realFile);
32409
32607
  if (opened.dev !== atPath.dev || opened.ino !== atPath.ino || path11.isAbsolute(fromRoot) || fromRoot === ".." || fromRoot.startsWith(`..${path11.sep}`)) {
@@ -38636,10 +38834,9 @@ var init_capabilities = __esm({
38636
38834
  });
38637
38835
 
38638
38836
  // ../shared/src/project-schemas.ts
38639
- var PROJECT_NAME_PATTERN, ProjectRefSchema, ProjectInfoSchema, ProjectListResponseSchema, ProjectResolveQuerySchema, ProjectResolveResponseSchema;
38837
+ var PROJECT_NAME_PATTERN, ProjectRefSchema, ProjectInfoSchema, ProjectListResponseSchema, ProjectResolveQuerySchema, ProjectResolveResponseSchema, AccountEligibilityRowSchema, AccountEligibilityQuerySchema, AccountEligibilityResponseSchema, ProjectAccountsRequestSchema, OnlyProjectsRequestSchema, OnlyProjectsResponseSchema;
38640
38838
  var init_project_schemas = __esm({
38641
38839
  "../shared/src/project-schemas.ts"() {
38642
- "use strict";
38643
38840
  init_zod();
38644
38841
  init_zod_openapi();
38645
38842
  extendZodWithOpenApiOnce();
@@ -38671,6 +38868,74 @@ var init_project_schemas = __esm({
38671
38868
  /** The project the folder belongs to, or null when it is in no repository. */
38672
38869
  project: ProjectRefSchema.nullable()
38673
38870
  }).openapi("ProjectResolveResponse");
38871
+ AccountEligibilityRowSchema = external_exports.object({
38872
+ /** The registry id, or `default` for Main (this computer's own sign-in). */
38873
+ id: external_exports.string(),
38874
+ /** What the person calls the account, or null when unnamed. */
38875
+ label: external_exports.string().nullable(),
38876
+ /** The color its dot is drawn in, lowercase `#rrggbb`. */
38877
+ color: external_exports.string(),
38878
+ /** True for Main when it has no registry row. */
38879
+ implicit: external_exports.boolean(),
38880
+ /** The projects the account is kept to, or null for any project. */
38881
+ onlyProjects: external_exports.array(ProjectRefSchema).nullable(),
38882
+ /** Whether the account's own rule lets it work here. */
38883
+ allowedByAccount: external_exports.boolean(),
38884
+ /** Whether the project's rule lets it work here (true with no project rule). */
38885
+ allowedByProject: external_exports.boolean(),
38886
+ /** Whether it may work here: both rules allow it. */
38887
+ eligible: external_exports.boolean()
38888
+ }).openapi("AccountEligibilityRow");
38889
+ AccountEligibilityQuerySchema = external_exports.object({
38890
+ /**
38891
+ * Any folder; the answer is for the project it belongs to. Leave it out for
38892
+ * a folder in no project.
38893
+ */
38894
+ project: external_exports.string().min(1).optional()
38895
+ }).openapi("AccountEligibilityQuery");
38896
+ AccountEligibilityResponseSchema = external_exports.object({
38897
+ /** The project the folder belongs to, or null when it is in no project. */
38898
+ project: ProjectRefSchema.nullable(),
38899
+ /** The project's own allow list, or null when it has none (every account). */
38900
+ allow: external_exports.array(external_exports.string()).nullable(),
38901
+ /** Every Claude account, in registry order, Main last when it has no row. */
38902
+ accounts: external_exports.array(AccountEligibilityRowSchema),
38903
+ /**
38904
+ * What a new chat in this folder would run on when nobody picks an account:
38905
+ * the launch ladder's own answer (the folder's agent's account, else the
38906
+ * default, skipping to the next account that may work here), or why it
38907
+ * would be refused. A picker's "Default" row names this, never a guess.
38908
+ * Absent on a server too old to say.
38909
+ */
38910
+ launch: external_exports.discriminatedUnion("ok", [
38911
+ external_exports.object({
38912
+ ok: external_exports.literal(true),
38913
+ /** The account's registry id, or `default` for Main. */
38914
+ accountId: external_exports.string(),
38915
+ /** The Claude folder it runs in. */
38916
+ root: external_exports.string()
38917
+ }),
38918
+ external_exports.object({
38919
+ ok: external_exports.literal(false),
38920
+ /** The plain sentence the launch would be refused with. */
38921
+ message: external_exports.string()
38922
+ })
38923
+ ]).optional()
38924
+ }).openapi("AccountEligibilityResponse");
38925
+ ProjectAccountsRequestSchema = external_exports.object({
38926
+ /** Any folder in the project. */
38927
+ project: external_exports.string().min(1),
38928
+ /** The account ids that may work there, or null to remove the project's rule. */
38929
+ allow: external_exports.array(external_exports.string().min(1)).nullable()
38930
+ }).openapi("ProjectAccountsRequest");
38931
+ OnlyProjectsRequestSchema = external_exports.object({
38932
+ /** Folders of the projects the account may work in, or null for any project. */
38933
+ projects: external_exports.array(external_exports.string().min(1)).nullable()
38934
+ }).openapi("OnlyProjectsRequest");
38935
+ OnlyProjectsResponseSchema = external_exports.object({
38936
+ /** The projects the account is now kept to, or null for any project. */
38937
+ onlyProjects: external_exports.array(ProjectRefSchema).nullable()
38938
+ }).openapi("OnlyProjectsResponse");
38674
38939
  }
38675
38940
  });
38676
38941
 
@@ -39171,9 +39436,10 @@ function isSafeSigninUrl(value) {
39171
39436
  if (url2.protocol !== "http:") return false;
39172
39437
  return url2.hostname === "localhost" || url2.hostname === "127.0.0.1" || url2.hostname === "[::1]";
39173
39438
  }
39174
- var PermissionModeSchema, PermissionModeIdSchema, PermissionStopSchema2, SessionTaskStatusSchema, StreamEventTypeSchema, QuestionOptionSchema, QuestionItemSchema, EffortLevelSchema, SessionOriginSchema, SessionLifecycleSchema, LimitPlanSchema, LimitStateSchema, SessionLimitSchema, ContinueAccountOptionSchema, ContinueOptionsResponseSchema, ContinueSessionRequestSchema, ContinueSessionResponseSchema, WaitForResetRequestSchema, LimitPlanResponseSchema, TrackerItemRefSchema, SessionSchema, SessionUpdateResponseSchema, SessionSettingsSchema, StoredSessionSettingsResponseSchema, UpdateSessionRequestSchema, ForkSessionRequestSchema, ReloadPluginsResultSchema, SEED_CONTEXT_MAX_LENGTH, MessageDispositionSchema, DispositionDowngradeReasonSchema, MessageDeliveryOutcomeSchema, InterruptOutcomeSchema, InterruptReasonSchema, InterruptReceiptSchema, QueuedMessageSchema, SendMessageRequestSchema, SendMessageResponseSchema, SessionTriggerResponseSchema, SessionQueueResponseSchema, QueueMoveTargetSchema, UpdateQueuedMessageRequestSchema, UpdateQueuedMessageResponseSchema, DENY_REASON_MAX_LENGTH, ApprovalRequestSchema, BatchApprovalRequestSchema, SubmitAnswersRequestSchema, UI_ACTION_ID_MAX_LENGTH, UI_ACTION_TITLE_MAX_LENGTH, UI_ACTION_PAYLOAD_MAX_LENGTH, UiActionRequestSchema, McpAppPermissionSchema, McpAppResourceRequestSchema, McpAppResourceResponseSchema, ElicitationModeSchema, ElicitationActionSchema, SubmitElicitationRequestSchema, ListSessionsQuerySchema, SessionListWarningSchema, SessionListResponseSchema, RecentSessionsQuerySchema, RecentSessionsResponseSchema, SessionDailyCountsQuerySchema, SessionDailyCountsResponseSchema, CommandsQuerySchema, TextDeltaSchema, ThinkingDeltaSchema, ToolCallStatusSchema, McpAppRefSchema, ToolCallEventSchema, ToolProgressEventSchema, AlwaysAllowScopeSchema, ApprovalEventSchema, QuestionPromptEventSchema, PendingInteractionDTOSchema, ErrorCategorySchema, ErrorEventSchema, ApiRetryEventSchema, DoneEventSchema, TerminalReasonSchema, UsageStateSchema, UsageStatusSchema, SessionStatusEventSchema, ContextUsageCategorySchema, ContextUsageSchema, TaskItemSchema, TaskUpdateEventSchema, RelayReceiptEventSchema, MessageDeliveredEventSchema, RelayMessageEventSchema, BackgroundTaskTypeSchema, BackgroundTaskStatusSchema, BackgroundTaskStartedEventSchema, BackgroundTaskProgressEventSchema, BackgroundTaskDoneEventSchema, SubagentTextDeltaEventSchema, SystemStatusEventSchema, OperationKindSchema, OperationStateSchema, OperationProgressEventShapeSchema, OperationProgressEventSchema, MemoryEntrySchema, MemoryRecallEventSchema, CompactBoundaryEventSchema, sessionImageShape, SessionImageEventSchema, deniedAgentShape, PermissionDeniedEventSchema, PromptSuggestionEventSchema, HookStartedEventSchema, HookProgressEventSchema, HookResponseEventSchema, SdkSessionStateSchema, SessionStateChangedEventSchema, ElicitationPromptEventSchema, ElicitationCompleteEventSchema, InteractionCancelledEventSchema, CapabilityApprovalRequiredEventSchema, CapabilityApprovalResolvedEventSchema, SigninUrlSchema, MCP_SIGNIN_OUTCOMES, McpSigninOutcomeSchema, McpSigninRequiredEventSchema, McpSigninResolvedEventSchema, StreamEventSchema, TextPartSchema, HookStatusSchema, HookPartSchema, ToolApprovalOutcomeSchema, QuestionOutcomeSchema, ToolCallPartSchema, BackgroundTaskPartSchema, ThinkingPartSchema, ErrorPartSchema, ElicitationPartSchema, CapabilityApprovalPartSchema, McpSigninPartSchema, MemoryRecallPartSchema, PermissionDeniedPartSchema, CompactBoundaryPartSchema, ImagePartSchema, MessagePartSchema, MessageTypeSchema, HistoryToolCallSchema, CompactMetadataSchema, HistoryMessageSchema, CommandEntrySchema, CommandRegistrySchema, FileListQuerySchema, RawFileQuerySchema, FileListResponseSchema, WriteFileRequestSchema, WriteFileResponseSchema, FileEntrySchema, FileTreeQuerySchema, FileTreeResponseSchema, FileContentQuerySchema, FileContentResponseSchema, CreateEntryRequestSchema, CreateEntryResponseSchema, DeleteEntryQuerySchema, RenameEntryRequestSchema, CopyEntryRequestSchema, RevealEntryRequestSchema, DiffBaselineOriginSchema, DiffBaselineQuerySchema, DiffBaselineResponseSchema, AdvanceDiffBaselineRequestSchema, DiffPendingQuerySchema, DiffPendingResponseSchema, DiffBaselineRawQuerySchema, RevertDiffBaselineRequestSchema, FileMutationResponseSchema, WorkbenchSignRequestSchema, WorkbenchSignResponseSchema, WorkbenchProbeRequestSchema, WorkbenchProbeResponseSchema, BrowseDirectoryQuerySchema, DirectoryEntrySchema, BrowseDirectoryResponseSchema, TunnelStatusSchema, HealthResponseSchema, ExecutionDefaultsSchema, ExperimentStateSchema, ServerConfigSchema, ModelTierSchema, ModelOptionSchema, SubagentInfoSchema, GitStatusResponseSchema, GitStatusErrorSchema, ErrorResponseSchema, SessionLockedErrorSchema, TaskStatusSchema, SettableTaskStatusSchema, TaskNameSchema, TaskRunStatusSchema, TaskRunTriggerSchema, TaskSchema, TaskRunSchema, CancelTaskRunResponseSchema, TaskTemplateSchema, TASK_DURATION_PATTERN, TASK_DURATION_MAX, TASK_DESCRIPTION_MAX, CreateTaskRequestSchema, SIDEBAR_TAB_ID_PATTERN, ShapeLiveLayoutCaptureSchema, ForkShapeRequestSchema, UpdateTaskRequestSchema, ListTaskRunsQuerySchema, ConfigPatchRequestSchema, ConfigPatchResponseSchema, UploadResultSchema, UploadResponseSchema, UploadProgressSchema, CanvasMediaSrcSchema, UiCanvasContentSchema, UiPanelIdSchema, UiToastLevelSchema, CELEBRATION_KINDS, CELEBRATION_KIND_SYNONYMS, CelebrationKindSchema, UiCommandTargetSchema, UiCommandSchema, UiCommandEventSchema, UiStateSchema, UiStateReportDocumentSchema, UiStateReportSchema, DevtoolsConsoleLevelSchema, DEVTOOLS_ARGS_MAX_CHARS, DevtoolsConsoleEntrySchema, DevtoolsNetworkEntrySchema, DEVTOOLS_CONSOLE_BATCH_MAX, DEVTOOLS_NETWORK_BATCH_MAX, DEVTOOLS_SCREENSHOT_MAX_CHARS, DevtoolsScreenshotResultSchema, DevtoolsIngestSchema, BrowserTargetSchema, BrowserActCommandSchema, BrowserPageSummarySchema, DEVTOOLS_OUTLINE_MAX_CHARS, DevtoolsActionResultSchema, DevtoolsRecordingUploadSchema;
39439
+ var PermissionModeSchema, PermissionModeIdSchema, PermissionStopSchema2, SessionTaskStatusSchema, StreamEventTypeSchema, QuestionOptionSchema, QuestionItemSchema, EffortLevelSchema, SessionOriginSchema, SessionLifecycleSchema, LimitPlanSchema, LimitStateSchema, SessionLimitSchema, ContinueAccountOptionSchema, ContinueOptionsResponseSchema, ContinueSessionRequestSchema, ContinueSessionResponseSchema, WaitForResetRequestSchema, LimitPlanResponseSchema, TrackerItemRefSchema, SessionStartedBySchema, SessionSchema, SessionUpdateResponseSchema, SessionSettingsSchema, StoredSessionSettingsResponseSchema, UpdateSessionRequestSchema, ForkSessionRequestSchema, ReloadPluginsResultSchema, SEED_CONTEXT_MAX_LENGTH, MessageDispositionSchema, DispositionDowngradeReasonSchema, MessageDeliveryOutcomeSchema, InterruptOutcomeSchema, InterruptReasonSchema, InterruptReceiptSchema, QueuedMessageSchema, SendMessageRequestSchema, SendMessageResponseSchema, SessionTriggerResponseSchema, SessionQueueResponseSchema, QueueMoveTargetSchema, UpdateQueuedMessageRequestSchema, UpdateQueuedMessageResponseSchema, DENY_REASON_MAX_LENGTH, ApprovalRequestSchema, BatchApprovalRequestSchema, SubmitAnswersRequestSchema, UI_ACTION_ID_MAX_LENGTH, UI_ACTION_TITLE_MAX_LENGTH, UI_ACTION_PAYLOAD_MAX_LENGTH, UiActionRequestSchema, McpAppPermissionSchema, McpAppResourceRequestSchema, McpAppResourceResponseSchema, ElicitationModeSchema, ElicitationActionSchema, SubmitElicitationRequestSchema, ListSessionsQuerySchema, SessionListWarningSchema, SessionListResponseSchema, RecentSessionsQuerySchema, RecentSessionsResponseSchema, SessionDailyCountsQuerySchema, SessionDailyCountsResponseSchema, CommandsQuerySchema, TextDeltaSchema, ThinkingDeltaSchema, ToolCallStatusSchema, McpAppRefSchema, ToolCallEventSchema, ToolProgressEventSchema, AlwaysAllowScopeSchema, ApprovalEventSchema, QuestionPromptEventSchema, PendingInteractionDTOSchema, ErrorCategorySchema, ErrorEventSchema, ApiRetryEventSchema, DoneEventSchema, TerminalReasonSchema, UsageStateSchema, UsageStatusSchema, SessionStatusEventSchema, ContextUsageCategorySchema, ContextUsageSchema, TaskItemSchema, TaskUpdateEventSchema, RelayReceiptEventSchema, MessageDeliveredEventSchema, RelayMessageEventSchema, BackgroundTaskTypeSchema, BackgroundTaskStatusSchema, BackgroundTaskStartedEventSchema, BackgroundTaskProgressEventSchema, BackgroundTaskDoneEventSchema, SubagentTextDeltaEventSchema, SystemStatusEventSchema, OperationKindSchema, OperationStateSchema, OperationProgressEventShapeSchema, OperationProgressEventSchema, MemoryEntrySchema, MemoryRecallEventSchema, CompactBoundaryEventSchema, sessionImageShape, SessionImageEventSchema, deniedAgentShape, PermissionDeniedEventSchema, PromptSuggestionEventSchema, HookStartedEventSchema, HookProgressEventSchema, HookResponseEventSchema, SdkSessionStateSchema, SessionStateChangedEventSchema, ElicitationPromptEventSchema, ElicitationCompleteEventSchema, InteractionCancelledEventSchema, CapabilityApprovalRequiredEventSchema, CapabilityApprovalResolvedEventSchema, SigninUrlSchema, MCP_SIGNIN_OUTCOMES, McpSigninOutcomeSchema, McpSigninRequiredEventSchema, McpSigninResolvedEventSchema, StreamEventSchema, TextPartSchema, HookStatusSchema, HookPartSchema, ToolApprovalOutcomeSchema, QuestionOutcomeSchema, ToolCallPartSchema, BackgroundTaskPartSchema, ThinkingPartSchema, ErrorPartSchema, ElicitationPartSchema, CapabilityApprovalPartSchema, McpSigninPartSchema, MemoryRecallPartSchema, PermissionDeniedPartSchema, CompactBoundaryPartSchema, ImagePartSchema, MessagePartSchema, MessageTypeSchema, HistoryToolCallSchema, CompactMetadataSchema, HistoryMessageSchema, CommandEntrySchema, CommandRegistrySchema, FileListQuerySchema, RawFileQuerySchema, FileListResponseSchema, WriteFileRequestSchema, WriteFileResponseSchema, FileEntrySchema, FileTreeQuerySchema, FileTreeResponseSchema, FileContentQuerySchema, FileContentResponseSchema, CreateEntryRequestSchema, CreateEntryResponseSchema, DeleteEntryQuerySchema, RenameEntryRequestSchema, CopyEntryRequestSchema, RevealEntryRequestSchema, DiffBaselineOriginSchema, DiffBaselineQuerySchema, DiffBaselineResponseSchema, AdvanceDiffBaselineRequestSchema, DiffPendingQuerySchema, DiffPendingResponseSchema, DiffBaselineRawQuerySchema, RevertDiffBaselineRequestSchema, FileMutationResponseSchema, WorkbenchSignRequestSchema, WorkbenchSignResponseSchema, WorkbenchProbeRequestSchema, WorkbenchProbeResponseSchema, BrowseDirectoryQuerySchema, DirectoryEntrySchema, BrowseDirectoryResponseSchema, TunnelStatusSchema, HealthResponseSchema, ExecutionDefaultsSchema, ExperimentStateSchema, ServerConfigSchema, ModelTierSchema, ModelOptionSchema, SubagentInfoSchema, GitStatusResponseSchema, GitStatusErrorSchema, ErrorResponseSchema, SessionLockedErrorSchema, TaskStatusSchema, SettableTaskStatusSchema, TaskNameSchema, TaskRunStatusSchema, TaskRunTriggerSchema, TaskSchema, TaskRunSchema, CancelTaskRunResponseSchema, TaskTemplateSchema, TASK_DURATION_PATTERN, TASK_DURATION_MAX, TASK_DESCRIPTION_MAX, CreateTaskRequestSchema, SIDEBAR_TAB_ID_PATTERN, ShapeLiveLayoutCaptureSchema, ForkShapeRequestSchema, UpdateTaskRequestSchema, ListTaskRunsQuerySchema, ConfigPatchRequestSchema, ConfigPatchResponseSchema, UploadResultSchema, UploadResponseSchema, UploadProgressSchema, CanvasMediaSrcSchema, UiCanvasContentSchema, UiPanelIdSchema, UiToastLevelSchema, CELEBRATION_KINDS, CELEBRATION_KIND_SYNONYMS, CelebrationKindSchema, UiCommandTargetSchema, UiCommandSchema, UiCommandEventSchema, UiStateSchema, UiStateReportDocumentSchema, UiStateReportSchema, DevtoolsConsoleLevelSchema, DEVTOOLS_ARGS_MAX_CHARS, DevtoolsConsoleEntrySchema, DevtoolsNetworkEntrySchema, DEVTOOLS_CONSOLE_BATCH_MAX, DEVTOOLS_NETWORK_BATCH_MAX, DEVTOOLS_SCREENSHOT_MAX_CHARS, DevtoolsScreenshotResultSchema, DevtoolsIngestSchema, BrowserTargetSchema, BrowserActCommandSchema, BrowserPageSummarySchema, DEVTOOLS_OUTLINE_MAX_CHARS, DevtoolsActionResultSchema, DevtoolsRecordingUploadSchema;
39175
39440
  var init_schemas3 = __esm({
39176
39441
  "../shared/src/schemas.ts"() {
39442
+ "use strict";
39177
39443
  init_zod();
39178
39444
  init_zod_openapi();
39179
39445
  init_additional_context();
@@ -39316,7 +39582,13 @@ var init_schemas3 = __esm({
39316
39582
  /** Why, in plain words. */
39317
39583
  reason: external_exports.string(),
39318
39584
  /** The advisor's badge, when it gave one. */
39319
- badge: external_exports.enum(["recommended", "reserved"]).optional()
39585
+ badge: external_exports.enum(["recommended", "reserved"]).optional(),
39586
+ /**
39587
+ * `true` when the account may not work in this session's project (spec
39588
+ * `flow-multiproject` §8.4): shown so a person sees why, never pickable,
39589
+ * and `reason` says which rule ("Only for client-app"). Absent otherwise.
39590
+ */
39591
+ notAllowed: external_exports.literal(true).optional()
39320
39592
  }).openapi("ContinueAccountOption");
39321
39593
  ContinueOptionsResponseSchema = external_exports.object({
39322
39594
  /** The session's current plan. */
@@ -39355,6 +39627,26 @@ var init_schemas3 = __esm({
39355
39627
  /** The chat the work runs in: the "Open its chat" target. Null for `this-chat`, or when it is not a DorkOS chat. */
39356
39628
  ownChatSessionId: external_exports.string().nullable()
39357
39629
  }).openapi("TrackerItemRef");
39630
+ SessionStartedBySchema = external_exports.discriminatedUnion("kind", [
39631
+ external_exports.object({
39632
+ kind: external_exports.literal("extension"),
39633
+ /** The extension's id. */
39634
+ extensionId: external_exports.string(),
39635
+ /** Its manifest name, as the first line says it. */
39636
+ extensionName: external_exports.string(),
39637
+ /** Why it was started (1-200). */
39638
+ reason: external_exports.string()
39639
+ }),
39640
+ external_exports.object({
39641
+ kind: external_exports.literal("chat"),
39642
+ /** The chat that started it: the first line's link. */
39643
+ sessionId: external_exports.string(),
39644
+ /** That chat's title, or null when this server cannot name it. */
39645
+ title: external_exports.string().nullable(),
39646
+ /** Why it was started, or null when the chat gave no reason. */
39647
+ reason: external_exports.string().nullable()
39648
+ })
39649
+ ]).openapi("SessionStartedBy");
39358
39650
  SessionSchema = external_exports.object({
39359
39651
  id: external_exports.string().uuid(),
39360
39652
  title: external_exports.string(),
@@ -39493,6 +39785,14 @@ var init_schemas3 = __esm({
39493
39785
  * their own (`via: 'own-chat'`). ABSENT when no run names this session.
39494
39786
  */
39495
39787
  trackerItems: external_exports.array(TrackerItemRefSchema).optional(),
39788
+ /**
39789
+ * Who started this chat, when an extension or another chat did (spec
39790
+ * `flow-multiproject` §7.7). Stamped from the server's own
39791
+ * `session_started_by` row by the session-origin overlays, on the session
39792
+ * routes and the live session list alike. ABSENT for a chat a person
39793
+ * started.
39794
+ */
39795
+ startedBy: SessionStartedBySchema.optional(),
39496
39796
  /**
39497
39797
  * ISO-8601 timestamp of the last message a PERSON sent in this session —
39498
39798
  * the server half of the sidebar's interaction-recency order key
@@ -41263,6 +41563,9 @@ var init_schemas3 = __esm({
41263
41563
  }),
41264
41564
  isAccountRoot: external_exports.boolean().openapi({
41265
41565
  description: "Whether DorkOS can currently find a Claude account here \u2014 the directory exists AND holds a `projects/` directory (the structural check, spec claude-code-accounts D4). Deliberately not named `exists`: a directory that exists without `projects/` reports false. False means it contributes no sessions"
41566
+ }),
41567
+ onlyProjects: external_exports.array(ProjectRefSchema).nullable().optional().openapi({
41568
+ description: 'The projects this account may work in ("Only for client-app"), or null for any project (spec flow-multiproject \xA78). Change it with PUT /api/runtimes/claude-code/accounts/:id/only-projects, never by writing it back through PATCH /api/config. Absent on a server too old to report it'
41266
41569
  })
41267
41570
  })
41268
41571
  ).openapi({ description: "The Claude accounts the operator has registered" }),
@@ -41281,6 +41584,19 @@ var init_schemas3 = __esm({
41281
41584
  }).optional().openapi({
41282
41585
  description: "Present only when the server process's own $CLAUDE_CONFIG_DIR decides where new sessions run (no default account is chosen) AND no row stands for that folder, so resolvedAccountId is absent: the variable and the folder it names. A launch-only override: the default account (Main) never follows it (shared account contract rev 6d)"
41283
41586
  }),
41587
+ defaultAccountOnlyProjects: external_exports.array(ProjectRefSchema).nullable().optional().openapi({
41588
+ description: "The projects Main (this computer's own Claude sign-in, id `default`) may work in, or null for any project (spec flow-multiproject \xA78). Absent on a server too old to report it"
41589
+ }),
41590
+ projectAccounts: external_exports.array(
41591
+ external_exports.object({
41592
+ project: ProjectRefSchema,
41593
+ allow: external_exports.array(external_exports.string()).openapi({
41594
+ description: "The account ids that may work in this project; `default` is Main"
41595
+ })
41596
+ })
41597
+ ).optional().openapi({
41598
+ description: "Each project that limits which accounts may work in it, by project name (spec flow-multiproject \xA78). A project that is not listed allows every account. Change it with PUT /api/runtimes/claude-code/project-accounts. Absent on a server too old to report it"
41599
+ }),
41284
41600
  accountsUnavailable: external_exports.boolean().optional().openapi({
41285
41601
  description: "True when the account registry could NOT be read (the config store threw, or was consulted before it was initialized), so `accounts` is empty because nothing could be learned rather than because nothing is registered. Absent means the list is an answer. A client must not judge an agent or session account reference against an unavailable registry \u2014 an override that cannot be verified is unknown, never wrong"
41286
41602
  }),
@@ -43208,12 +43524,12 @@ function substitutePlaceholders(value) {
43208
43524
  return value;
43209
43525
  }
43210
43526
  function getValueAtPath(value, path53) {
43211
- let current = value;
43527
+ let current2 = value;
43212
43528
  for (const segment of path53) {
43213
- if (current === null || typeof current !== "object") return void 0;
43214
- current = current[segment];
43529
+ if (current2 === null || typeof current2 !== "object") return void 0;
43530
+ current2 = current2[segment];
43215
43531
  }
43216
- return current;
43532
+ return current2;
43217
43533
  }
43218
43534
  var WHOLE_PLACEHOLDER_PATTERN, PLACEHOLDER_DUMMY_VALUE, WidgetTemplateSchema;
43219
43535
  var init_ui_template = __esm({
@@ -43532,7 +43848,6 @@ async function measurePackageTree(root, limits = PACKAGE_SIZE_LIMITS, { countGit
43532
43848
  var PACKAGE_SIZE_LIMITS, CLONE_SIZE_LIMITS, PackageTooLargeError;
43533
43849
  var init_package_size = __esm({
43534
43850
  "../marketplace/src/package-size.ts"() {
43535
- "use strict";
43536
43851
  PACKAGE_SIZE_LIMITS = {
43537
43852
  maxTotalBytes: 250 * 1024 * 1024,
43538
43853
  maxEntries: 2e4,
@@ -43725,10 +44040,10 @@ async function readPackageFile(packagePath, relPath2) {
43725
44040
  }
43726
44041
  }
43727
44042
  async function reachedThroughLink(packagePath, relDir) {
43728
- let current = packagePath;
44043
+ let current2 = packagePath;
43729
44044
  for (const part of path18.normalize(relDir).split(path18.sep)) {
43730
- current = path18.join(current, part);
43731
- if ((await fs8.lstat(current)).isSymbolicLink()) return true;
44045
+ current2 = path18.join(current2, part);
44046
+ if ((await fs8.lstat(current2)).isSymbolicLink()) return true;
43732
44047
  }
43733
44048
  return false;
43734
44049
  }
@@ -44972,6 +45287,11 @@ var init_config_disclosure = __esm({
44972
45287
  // The copies a person declined in the inbox (DOR-2517): absolute paths on
44973
45288
  // this machine again, and nothing an agent needs to do its work.
44974
45289
  "extensions.dismissedApprovals": "withhold",
45290
+ // The code sources a person trusts (spec `flow-multiproject` §9.3). Not a
45291
+ // secret, but nothing an agent needs to do its work, and the list says which
45292
+ // code this machine runs without asking.
45293
+ "extensions.trustedSources[].source": "withhold",
45294
+ "extensions.trustedSources[].trustedAt": "withhold",
44975
45295
  "mcp.enabled": "expose",
44976
45296
  "mcp.apiKey": "withhold",
44977
45297
  "mcp.rateLimit.enabled": "expose",
@@ -45046,6 +45366,13 @@ var init_config_disclosure = __esm({
45046
45366
  // (spec claude-account-ui §7.4). Folder paths, the same class as
45047
45367
  // `accounts[].path` above: exposed on purpose, and naming no secret.
45048
45368
  "runtimes.claudeCode.dismissedFolders": "expose",
45369
+ // Which projects each account may work in, and which accounts each project
45370
+ // may use (spec `flow-multiproject` §8): absolute folders on this machine, and
45371
+ // nothing an agent needs. A launch it asks for that the rules refuse is
45372
+ // answered with a sentence naming the project, which is all it can act on.
45373
+ "runtimes.claudeCode.accounts[].onlyProjects": "withhold",
45374
+ "runtimes.claudeCode.defaultAccountOnlyProjects": "withhold",
45375
+ "runtimes.claudeCode.projectAccounts": "withhold",
45049
45376
  // The execution defaults a new session on each runtime starts with. A model id
45050
45377
  // and an effort rung are the same class of thing as `runtimes.default`: they
45051
45378
  // describe HOW work runs here, name no credential and no person, and an agent
@@ -45530,6 +45857,12 @@ var init_config_write_policy = __esm({
45530
45857
  // Their answer to a consent question: a caller that could write it could
45531
45858
  // hide the question from them.
45532
45859
  "extensions.dismissedApprovals": "operator-only",
45860
+ // The code sources a person trusts outright (spec `flow-multiproject` §9.3):
45861
+ // every extension provably from one runs without asking. It decides which
45862
+ // code runs, and trusting a new source is one of the three asks only a
45863
+ // person can answer.
45864
+ "extensions.trustedSources[].source": "operator-only",
45865
+ "extensions.trustedSources[].trustedAt": "operator-only",
45533
45866
  // Whether the external tool endpoint answers, the bearer that gates it, and the
45534
45867
  // rate limits that bound abuse of it.
45535
45868
  "mcp.enabled": "operator-only",
@@ -45645,6 +45978,14 @@ var init_config_write_policy = __esm({
45645
45978
  // accounts a person is shown as addable, so it stays with the roster it
45646
45979
  // curates: only a person curates it, through the dismiss route.
45647
45980
  "runtimes.claudeCode.dismissedFolders": "operator-only",
45981
+ // Which projects each Claude account may work in, and which accounts each
45982
+ // project may use (spec `flow-multiproject` §8). They bound where a credential
45983
+ // may be used, so an agent that could write them could move spend onto an
45984
+ // account the person kept out of that project. Written by a person through
45985
+ // the two `PUT /api/runtimes/claude-code/...` routes behind the person bar.
45986
+ "runtimes.claudeCode.accounts[].onlyProjects": "operator-only",
45987
+ "runtimes.claudeCode.defaultAccountOnlyProjects": "operator-only",
45988
+ "runtimes.claudeCode.projectAccounts": "operator-only",
45648
45989
  // The execution defaults for new sessions on each runtime. Writable, and the
45649
45990
  // operator was asked directly: a model and an effort level are a preference
45650
45991
  // about how work runs, on the same footing as `runtimes.default` right above,
@@ -45793,7 +46134,10 @@ var init_config_write_policy = __esm({
45793
46134
  "runtimes.claudeCode.accounts[].label",
45794
46135
  "runtimes.claudeCode.accounts[].color",
45795
46136
  "runtimes.claudeCode.defaultAccountColor",
45796
- "runtimes.claudeCode.dismissedFolders"
46137
+ "runtimes.claudeCode.dismissedFolders",
46138
+ "runtimes.claudeCode.accounts[].onlyProjects",
46139
+ "runtimes.claudeCode.defaultAccountOnlyProjects",
46140
+ "runtimes.claudeCode.projectAccounts"
45797
46141
  ]
45798
46142
  },
45799
46143
  {
@@ -45810,6 +46154,8 @@ var init_config_write_policy = __esm({
45810
46154
  "extensions.approvedToRun",
45811
46155
  "extensions.approvedSources",
45812
46156
  "extensions.dismissedApprovals",
46157
+ "extensions.trustedSources[].source",
46158
+ "extensions.trustedSources[].trustedAt",
45813
46159
  "harness.approvedHooks",
45814
46160
  "harness.refusedHooks",
45815
46161
  "runtimes.opencode.binaryPath",
@@ -47286,6 +47632,13 @@ function permissionSeedForOrigin(origin) {
47286
47632
  // binding it was bridged from.
47287
47633
  case "room":
47288
47634
  return origin.externalAuthor ? "none" : "configured-stop-on-insert";
47635
+ // Work an extension started in a brand-new chat in the person's project.
47636
+ // The id was minted for this start a moment earlier, so there is no row a
47637
+ // person's earlier settings change could have made, and "on insert" is
47638
+ // the honest name for it: the operator's configured stop, the same default
47639
+ // a new chat of their own gets (spec `full-power-defaults`).
47640
+ case "extension-start":
47641
+ return "configured-stop-on-insert";
47289
47642
  // Everything below seeds nothing, for two different reasons.
47290
47643
  //
47291
47644
  // A schedule's power is already decided and already stored, on the schedule
@@ -54425,38 +54778,48 @@ var sessionMetadata, sessionMessageQueue, sessionStagedContext;
54425
54778
  var init_sessions = __esm({
54426
54779
  "../db/src/schema/sessions.ts"() {
54427
54780
  "use strict";
54781
+ init_drizzle_orm();
54428
54782
  init_sqlite_core();
54429
- sessionMetadata = sqliteTable("session_metadata", {
54430
- // --- Immutable identity (first-write-wins; ADR-0255) ---
54431
- sessionId: text("session_id").primaryKey(),
54432
- // NULL = this session has not started yet, so nothing has said which runtime
54433
- // owns it. A settings change made before the first message creates the row
54434
- // (that is E3's pre-launch picker), and a preference is not a binding: the
54435
- // first turn carries the person's runtime choice and is what claims the row
54436
- // (DOR-812). Readers resolve an unbound row exactly like a row-less one — by
54437
- // inference, unpersisted — so nothing is blocked in the meantime.
54438
- runtime: text("runtime"),
54439
- agentPath: text("agent_path"),
54440
- // What started the session (`TurnOrigin.kind`), written by the same
54441
- // first-write-wins statement that binds the runtime and never overwritten.
54442
- // Server-held, unlike the best-effort `Session.origin`, so it is what decides
54443
- // whether a limited session may carry its work to another account (spec
54444
- // `claude-account-fleet` D9). NULL = bound before this column existed.
54445
- launchOrigin: text("launch_origin"),
54446
- // The episode `resetsAt` (else `since`) of the last usage limit core resumed
54447
- // this session from by itself (spec `claude-account-fleet` D9 "Wait, then
54448
- // resume by itself"): at most one automatic resume per window reset. Kept
54449
- // here, not on the `session_limits` row, because the resumed turn's own
54450
- // `turn_start` deletes that row. NULL = never resumed automatically.
54451
- lastAutoResumeFor: text("last_auto_resume_for"),
54452
- createdAt: text("created_at").notNull(),
54453
- // --- Mutable per-session settings (last-write-wins; ADR-0260) ---
54454
- // NULL = "no explicit preference; use the runtime's default."
54455
- permissionMode: text("permission_mode"),
54456
- model: text("model"),
54457
- effort: text("effort"),
54458
- fastMode: integer2("fast_mode", { mode: "boolean" })
54459
- });
54783
+ sessionMetadata = sqliteTable(
54784
+ "session_metadata",
54785
+ {
54786
+ // --- Immutable identity (first-write-wins; ADR-0255) ---
54787
+ sessionId: text("session_id").primaryKey(),
54788
+ // NULL = this session has not started yet, so nothing has said which runtime
54789
+ // owns it. A settings change made before the first message creates the row
54790
+ // (that is E3's pre-launch picker), and a preference is not a binding: the
54791
+ // first turn carries the person's runtime choice and is what claims the row
54792
+ // (DOR-812). Readers resolve an unbound row exactly like a row-less one — by
54793
+ // inference, unpersisted — so nothing is blocked in the meantime.
54794
+ runtime: text("runtime"),
54795
+ agentPath: text("agent_path"),
54796
+ // What started the session (`TurnOrigin.kind`), written by the same
54797
+ // first-write-wins statement that binds the runtime and never overwritten.
54798
+ // Server-held, unlike the best-effort `Session.origin`, so it is what decides
54799
+ // whether a limited session may carry its work to another account (spec
54800
+ // `claude-account-fleet` D9). NULL = bound before this column existed.
54801
+ launchOrigin: text("launch_origin"),
54802
+ // The episode `resetsAt` (else `since`) of the last usage limit core resumed
54803
+ // this session from by itself (spec `claude-account-fleet` D9 "Wait, then
54804
+ // resume by itself"): at most one automatic resume per window reset. Kept
54805
+ // here, not on the `session_limits` row, because the resumed turn's own
54806
+ // `turn_start` deletes that row. NULL = never resumed automatically.
54807
+ lastAutoResumeFor: text("last_auto_resume_for"),
54808
+ createdAt: text("created_at").notNull(),
54809
+ // --- Mutable per-session settings (last-write-wins; ADR-0260) ---
54810
+ // NULL = "no explicit preference; use the runtime's default."
54811
+ permissionMode: text("permission_mode"),
54812
+ model: text("model"),
54813
+ effort: text("effort"),
54814
+ fastMode: integer2("fast_mode", { mode: "boolean" })
54815
+ },
54816
+ // `listSessionIdsForAgentPath` answers "which sessions belong to this agent"
54817
+ // for every agent's session list, and there is one row per session ever
54818
+ // started, so without this it read the whole table per request.
54819
+ (t2) => [
54820
+ index("session_metadata_agent_path_idx").on(t2.agentPath).where(sql`${t2.agentPath} IS NOT NULL`)
54821
+ ]
54822
+ );
54460
54823
  sessionMessageQueue = sqliteTable(
54461
54824
  "session_message_queue",
54462
54825
  {
@@ -54550,9 +54913,11 @@ var init_session_events = __esm({
54550
54913
  payload: text("payload").notNull(),
54551
54914
  createdAt: text("created_at").notNull()
54552
54915
  },
54916
+ // The primary key is the only index: it already orders one session's events by
54917
+ // seq. A second `(session_id, seq)` index sat here until the index audit
54918
+ // (migration 0134) and cost every event written a second b-tree insert.
54553
54919
  (t2) => ({
54554
- pk: primaryKey({ columns: [t2.sessionId, t2.seq] }),
54555
- bySession: index("session_events_session_idx").on(t2.sessionId, t2.seq)
54920
+ pk: primaryKey({ columns: [t2.sessionId, t2.seq] })
54556
54921
  })
54557
54922
  );
54558
54923
  }
@@ -54727,6 +55092,45 @@ var init_session_context = __esm({
54727
55092
  }
54728
55093
  });
54729
55094
 
55095
+ // ../db/src/schema/session/session-started-by.ts
55096
+ var sessionStartedBy;
55097
+ var init_session_started_by = __esm({
55098
+ "../db/src/schema/session/session-started-by.ts"() {
55099
+ "use strict";
55100
+ init_drizzle_orm();
55101
+ init_sqlite_core();
55102
+ sessionStartedBy = sqliteTable(
55103
+ "session_started_by",
55104
+ {
55105
+ /** The started chat's canonical id. */
55106
+ sessionId: text("session_id").primaryKey(),
55107
+ /** What started it. */
55108
+ kind: text("kind", { enum: ["extension", "chat"] }).notNull(),
55109
+ /** The extension that started it, for `kind = 'extension'`. */
55110
+ extensionId: text("extension_id"),
55111
+ /** The chat that started it, for `kind = 'chat'`. */
55112
+ startedBySessionId: text("started_by_session_id"),
55113
+ /** The extension at the root of the chain, or NULL when none. */
55114
+ originExtensionId: text("origin_extension_id"),
55115
+ /** Why it was started, in plain words (≤ 200), or NULL when none was given. */
55116
+ reason: text("reason"),
55117
+ /**
55118
+ * A chat carried to another account from a started one (a move, not new
55119
+ * work): it keeps the chain, and it is never refused by, nor counted in,
55120
+ * the hourly limit.
55121
+ */
55122
+ carried: integer2("carried", { mode: "boolean" }).notNull().default(false),
55123
+ /** When it was started (ISO 8601). */
55124
+ createdAt: text("created_at").notNull()
55125
+ },
55126
+ (table2) => [
55127
+ index("session_started_by_origin_created_idx").on(table2.originExtensionId, table2.createdAt),
55128
+ check2("session_started_by_kind", sql`${table2.kind} IN ('extension', 'chat')`)
55129
+ ]
55130
+ );
55131
+ }
55132
+ });
55133
+
54730
55134
  // ../db/src/schema/workspace.ts
54731
55135
  var workspaces;
54732
55136
  var init_workspace2 = __esm({
@@ -54963,7 +55367,7 @@ var init_unclaimed_chats = __esm({
54963
55367
  });
54964
55368
 
54965
55369
  // ../db/src/schema/connectors/connections.ts
54966
- var connectorProviderInstances, connections, connectorOperationRevisions, connectionOperationGrants, EVERY_AGENT_GRANT_SUBJECT_ID, agentConnectionAttachments, sessionConnectionOverrides, connectorLegacyAgentRevocations, connectorApplicationMigrations;
55370
+ var connectorProviderInstances, connections, connectorOperationRevisions, connectionOperationGrants, EVERY_AGENT_GRANT_SUBJECT_ID, connectionAccessLevels, connectionLevelFollows, agentConnectionAttachments, sessionConnectionOverrides, connectorLegacyAgentRevocations, connectorApplicationMigrations;
54967
55371
  var init_connections = __esm({
54968
55372
  "../db/src/schema/connectors/connections.ts"() {
54969
55373
  "use strict";
@@ -55120,6 +55524,36 @@ var init_connections = __esm({
55120
55524
  ]
55121
55525
  );
55122
55526
  EVERY_AGENT_GRANT_SUBJECT_ID = "every_agent";
55527
+ connectionAccessLevels = sqliteTable(
55528
+ "connection_access_levels",
55529
+ {
55530
+ subjectType: text("subject_type", { enum: ["agent", "every_agent"] }).notNull(),
55531
+ subjectId: text("subject_id").notNull(),
55532
+ /** The one agent a row speaks for; null only on an `every_agent` row. */
55533
+ agentId: text("agent_id"),
55534
+ connectionId: text("connection_id").notNull().references(() => connections.id, { onDelete: "cascade" }),
55535
+ level: text("level", { enum: ["read", "read-write"] }).notNull(),
55536
+ createdBy: text("created_by").notNull(),
55537
+ updatedAt: text("updated_at").notNull(),
55538
+ /**
55539
+ * The hosted command DorkOS staged on its own to follow the app, while it
55540
+ * is the latest one for this level. Hosted authority refusing THAT command
55541
+ * keeps the level (the next pass sends it again); refusing a change the
55542
+ * owner made ends it. Null once the owner chooses again.
55543
+ */
55544
+ followerCommandId: text("follower_command_id")
55545
+ },
55546
+ (table2) => [
55547
+ primaryKey({ columns: [table2.subjectType, table2.subjectId, table2.connectionId] }),
55548
+ index("connection_access_levels_agent_idx").on(table2.agentId),
55549
+ index("connection_access_levels_connection_idx").on(table2.connectionId)
55550
+ ]
55551
+ );
55552
+ connectionLevelFollows = sqliteTable("connection_level_follows", {
55553
+ connectionId: text("connection_id").primaryKey().references(() => connections.id, { onDelete: "cascade" }),
55554
+ followedAt: text("followed_at").notNull(),
55555
+ appVersion: text("app_version").notNull()
55556
+ });
55123
55557
  agentConnectionAttachments = sqliteTable(
55124
55558
  "agent_connection_attachments",
55125
55559
  {
@@ -56142,7 +56576,14 @@ var init_rooms = __esm({
56142
56576
  /** The `(member, room)` read cursor — the highest `seq` this member has seen. */
56143
56577
  lastReadSeq: integer2("last_read_seq").notNull().default(0)
56144
56578
  },
56145
- (table2) => [primaryKey({ columns: [table2.roomId, table2.authorId] })]
56579
+ (table2) => [
56580
+ primaryKey({ columns: [table2.roomId, table2.authorId] }),
56581
+ // "Every room this author is in" (`listMembershipsFor`), asked by the room
56582
+ // directory, room search and the member directory on every request. The
56583
+ // primary key leads with room_id, so without this each call read the whole
56584
+ // table, and a mirrored Community room adds a row per remote author.
56585
+ index("idx_room_members_author").on(table2.authorId)
56586
+ ]
56146
56587
  );
56147
56588
  roomDepartedSeats = sqliteTable(
56148
56589
  "room_departed_seats",
@@ -56273,7 +56714,17 @@ var init_rooms = __esm({
56273
56714
  // hot path, inside the `seq`-allocating transaction — pays one more b-tree
56274
56715
  // write. Taken because the read it serves runs on every room-list request,
56275
56716
  // where the alternative is a full scan of the largest table in the schema.
56276
- index("idx_room_entries_author_room").on(table2.authorId, table2.roomId)
56717
+ //
56718
+ // **`thread_root_entry_id` is the third column for `listThreadsForMember`**
56719
+ // (migration 0134). Its "did this author post in this thread" EXISTS runs
56720
+ // once per reply in every room, and with two columns the planner (no
56721
+ // statistics, as above) answered it from `(author_id, room_id)` and read
56722
+ // every row the author ever wrote in that room, per reply: 10.9 seconds for
56723
+ // one thread list on a 500,000-entry install. With the third column the
56724
+ // check is one covering lookup, and the whole list went from 137M to 4.3M
56725
+ // VM steps (10.9 s to 0.4 s). Widening this index
56726
+ // rather than adding one keeps the insert cost where it was.
56727
+ index("idx_room_entries_author_room").on(table2.authorId, table2.roomId, table2.threadRootEntryId)
56277
56728
  ]
56278
56729
  );
56279
56730
  roomEntryReactions = sqliteTable(
@@ -56654,7 +57105,11 @@ var init_read_cursors = __esm({
56654
57105
  // it: an interpolated `0` becomes a bind parameter, and drizzle-kit writes
56655
57106
  // the marker into the migration file, where `>= ?` is a syntax error the
56656
57107
  // first time the migration runs.
56657
- check2("read_cursors_last_read_seq", sql`${table2.lastReadSeq} >= ${sql.raw("0")}`)
57108
+ check2("read_cursors_last_read_seq", sql`${table2.lastReadSeq} >= ${sql.raw("0")}`),
57109
+ // Everyone's cursor on one thread (`listForThread`), read each time a room
57110
+ // opens. The primary key leads with the person, and every session a person
57111
+ // opens adds a row, so without this each room open read the whole table.
57112
+ index("idx_read_cursors_thread").on(table2.threadKind, table2.threadId)
56658
57113
  ]
56659
57114
  );
56660
57115
  }
@@ -56785,6 +57240,7 @@ var communityRoomMirrors, communityMirrorAccess, communityMirrorEntries, communi
56785
57240
  var init_community_mirrors = __esm({
56786
57241
  "../db/src/schema/communities/community-mirrors.ts"() {
56787
57242
  "use strict";
57243
+ init_drizzle_orm();
56788
57244
  init_sqlite_core();
56789
57245
  communityRoomMirrors = sqliteTable(
56790
57246
  "community_room_mirrors",
@@ -56860,8 +57316,7 @@ var init_community_mirrors = __esm({
56860
57316
  table2.localRoomId,
56861
57317
  table2.remoteSeq
56862
57318
  ),
56863
- uniqueIndex("community_mirror_entries_local_entry_unique").on(table2.localEntryId),
56864
- index("idx_community_mirror_entries_room_seq").on(table2.localRoomId, table2.remoteSeq)
57319
+ uniqueIndex("community_mirror_entries_local_entry_unique").on(table2.localEntryId)
56865
57320
  ]
56866
57321
  );
56867
57322
  communityMirrorRedactions = sqliteTable(
@@ -56909,7 +57364,12 @@ var init_community_mirrors = __esm({
56909
57364
  table2.idempotencyKey
56910
57365
  ),
56911
57366
  index("idx_community_outbox_state_expiry").on(table2.state, table2.expiresAt),
56912
- index("idx_community_outbox_ref_state").on(table2.communityRef, table2.state)
57367
+ index("idx_community_outbox_ref_state").on(table2.communityRef, table2.state),
57368
+ // The local copies of one Community entry (`localCopiesOf`), asked once per
57369
+ // redaction the Community sends. The outbox is never pruned, and the other
57370
+ // indexes stop at community_ref, so each redaction read every post this
57371
+ // install ever delivered to that Community.
57372
+ index("idx_community_outbox_remote_entry").on(table2.communityRef, table2.remoteRoomId, table2.remoteEntryId).where(sql`${table2.remoteEntryId} IS NOT NULL`)
56913
57373
  ]
56914
57374
  );
56915
57375
  communityEntryOrigins = sqliteTable(
@@ -57456,6 +57916,8 @@ __export(schema_exports, {
57456
57916
  communityMirrorRedactions: () => communityMirrorRedactions,
57457
57917
  communityOutbox: () => communityOutbox,
57458
57918
  communityRoomMirrors: () => communityRoomMirrors,
57919
+ connectionAccessLevels: () => connectionAccessLevels,
57920
+ connectionLevelFollows: () => connectionLevelFollows,
57459
57921
  connectionOperationGrants: () => connectionOperationGrants,
57460
57922
  connections: () => connections,
57461
57923
  connectorAgentRequests: () => connectorAgentRequests,
@@ -57523,6 +57985,7 @@ __export(schema_exports, {
57523
57985
  sessionMetadata: () => sessionMetadata,
57524
57986
  sessionRelations: () => sessionRelations,
57525
57987
  sessionStagedContext: () => sessionStagedContext,
57988
+ sessionStartedBy: () => sessionStartedBy,
57526
57989
  unclaimedChats: () => unclaimedChats,
57527
57990
  user: () => user,
57528
57991
  userRelations: () => userRelations,
@@ -57547,6 +58010,7 @@ var init_schema2 = __esm({
57547
58010
  init_session_limits();
57548
58011
  init_session_limit_history();
57549
58012
  init_session_context();
58013
+ init_session_started_by();
57550
58014
  init_workspace2();
57551
58015
  init_auth();
57552
58016
  init_unclaimed_chats();
@@ -57695,6 +58159,18 @@ var init_session_limit_store = __esm({
57695
58159
  }
57696
58160
  });
57697
58161
 
58162
+ // ../../apps/server/src/services/session/origin/session-started-by-store.ts
58163
+ function getSessionStartedByStore() {
58164
+ return current;
58165
+ }
58166
+ var current;
58167
+ var init_session_started_by_store = __esm({
58168
+ "../../apps/server/src/services/session/origin/session-started-by-store.ts"() {
58169
+ "use strict";
58170
+ init_src2();
58171
+ }
58172
+ });
58173
+
57698
58174
  // ../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/version.js
57699
58175
  var VERSION;
57700
58176
  var init_version3 = __esm({
@@ -59715,6 +60191,7 @@ var init_runtime_registry = __esm({
59715
60191
  init_src2();
59716
60192
  init_logger();
59717
60193
  init_session_limit_store();
60194
+ init_session_started_by_store();
59718
60195
  init_observability();
59719
60196
  BOUND_RUNTIME_CHUNK_SIZE = 500;
59720
60197
  RuntimeNotRegisteredError = class extends Error {
@@ -60322,6 +60799,15 @@ var init_runtime_registry = __esm({
60322
60799
  err: err instanceof Error ? err.message : String(err)
60323
60800
  });
60324
60801
  }
60802
+ try {
60803
+ getSessionStartedByStore()?.move(fromId, toId);
60804
+ } catch (err) {
60805
+ logger.warn("[RuntimeRegistry] could not move who started a session", {
60806
+ fromId,
60807
+ toId,
60808
+ err: err instanceof Error ? err.message : String(err)
60809
+ });
60810
+ }
60325
60811
  const source = db.select().from(sessionMetadata).where(eq(sessionMetadata.sessionId, fromId)).get();
60326
60812
  if (!source) return;
60327
60813
  const destination = db.select().from(sessionMetadata).where(eq(sessionMetadata.sessionId, toId)).get();
@@ -62262,6 +62748,58 @@ var init_task_origin_overlay = __esm({
62262
62748
  }
62263
62749
  });
62264
62750
 
62751
+ // ../../apps/server/src/services/session/origin/started-by-origin-overlay.ts
62752
+ function rememberTitle(session2) {
62753
+ if (!session2.title) return;
62754
+ knownTitles.delete(session2.id);
62755
+ knownTitles.set(session2.id, session2.title);
62756
+ if (knownTitles.size > TITLE_MEMORY) {
62757
+ const oldest = knownTitles.keys().next().value;
62758
+ if (oldest !== void 0) knownTitles.delete(oldest);
62759
+ }
62760
+ }
62761
+ function toStartedBy(record2, nameOf, titleOf) {
62762
+ if (record2.kind === "extension") {
62763
+ if (!record2.extensionId) return null;
62764
+ return {
62765
+ kind: "extension",
62766
+ extensionId: record2.extensionId,
62767
+ extensionName: nameOf(record2.extensionId),
62768
+ reason: record2.reason ?? ""
62769
+ };
62770
+ }
62771
+ if (!record2.startedBySessionId) return null;
62772
+ return {
62773
+ kind: "chat",
62774
+ sessionId: record2.startedBySessionId,
62775
+ title: titleOf(record2.startedBySessionId),
62776
+ reason: record2.reason
62777
+ };
62778
+ }
62779
+ function applyStartedByOverlay(sessions, resolveStartedBy, nameOf) {
62780
+ if (sessions.length === 0) return;
62781
+ for (const session2 of sessions) rememberTitle(session2);
62782
+ if (!resolveStartedBy) return;
62783
+ const starts = resolveStartedBy(sessions.map((s2) => s2.id));
62784
+ if (starts.size === 0) return;
62785
+ const titleOf = (id) => knownTitles.get(id) ?? null;
62786
+ for (const session2 of sessions) {
62787
+ const record2 = starts.get(session2.id);
62788
+ if (!record2) continue;
62789
+ const startedBy = toStartedBy(record2, nameOf ?? ((id) => id), titleOf);
62790
+ if (!startedBy) continue;
62791
+ session2.startedBy = startedBy;
62792
+ }
62793
+ }
62794
+ var TITLE_MEMORY, knownTitles;
62795
+ var init_started_by_origin_overlay = __esm({
62796
+ "../../apps/server/src/services/session/origin/started-by-origin-overlay.ts"() {
62797
+ "use strict";
62798
+ TITLE_MEMORY = 2e3;
62799
+ knownTitles = /* @__PURE__ */ new Map();
62800
+ }
62801
+ });
62802
+
62265
62803
  // ../../apps/server/src/services/session/origin/session-origin-overlays.ts
62266
62804
  function sessionOriginOverlaySteps(resolvers) {
62267
62805
  return [
@@ -62272,6 +62810,10 @@ function sessionOriginOverlaySteps(resolvers) {
62272
62810
  {
62273
62811
  name: "Pulse task origin",
62274
62812
  apply: (sessions) => applyTaskOriginOverlay(sessions, resolvers.resolveTaskOrigins)
62813
+ },
62814
+ {
62815
+ name: "started by",
62816
+ apply: (sessions) => applyStartedByOverlay(sessions, resolvers.resolveStartedBy, resolvers.extensionNameOf)
62275
62817
  }
62276
62818
  ];
62277
62819
  }
@@ -62280,6 +62822,7 @@ var init_session_origin_overlays = __esm({
62280
62822
  "use strict";
62281
62823
  init_room_origin_overlay();
62282
62824
  init_task_origin_overlay();
62825
+ init_started_by_origin_overlay();
62283
62826
  }
62284
62827
  });
62285
62828
 
@@ -62961,6 +63504,18 @@ var init_project_registry = __esm({
62961
63504
  this.listeners.delete(listener);
62962
63505
  };
62963
63506
  }
63507
+ /**
63508
+ * The root of a named folder, with the boundary applied to both ends, and
63509
+ * nothing recorded: no `reported` row, no reporter, no cap slot. For a caller
63510
+ * that only accepts projects already known (starting work, spec §7.7), where
63511
+ * a refusal must leave no trace.
63512
+ *
63513
+ * @param dir - Any folder.
63514
+ * @returns The canonical root, null (no repository), or `'outside'`.
63515
+ */
63516
+ rootWithin(dir) {
63517
+ return this.boundedRoot(dir);
63518
+ }
62964
63519
  /** The root of a named folder, with the boundary applied to both ends. */
62965
63520
  async boundedRoot(dir) {
62966
63521
  let checked;
@@ -63015,8 +63570,8 @@ var init_project_registry = __esm({
63015
63570
  }
63016
63571
  /** Record that an extension named a root; persisted first, then kept. */
63017
63572
  addReporter(root, extensionId, kind) {
63018
- const current = this.reporters.get(root)?.get(extensionId);
63019
- if (current === "report" || current === kind) return;
63573
+ const current2 = this.reporters.get(root)?.get(extensionId);
63574
+ if (current2 === "report" || current2 === kind) return;
63020
63575
  const reporter = {
63021
63576
  root,
63022
63577
  extensionId,
@@ -63676,6 +64231,68 @@ var init_claude_config_env_lock = __esm({
63676
64231
  }
63677
64232
  });
63678
64233
 
64234
+ // ../../apps/server/src/services/core/usage/account-eligibility.ts
64235
+ var init_account_eligibility = __esm({
64236
+ "../../apps/server/src/services/core/usage/account-eligibility.ts"() {
64237
+ "use strict";
64238
+ init_canonical_directory();
64239
+ init_account_usage();
64240
+ init_config_schema();
64241
+ init_project_schemas();
64242
+ init_project_registry();
64243
+ }
64244
+ });
64245
+
64246
+ // ../../apps/server/src/services/core/usage/account-advisor.ts
64247
+ var RankingRowSchema, RankingSchema, LimitedPlanSchema, CarryOverSeedSchema;
64248
+ var init_account_advisor = __esm({
64249
+ "../../apps/server/src/services/core/usage/account-advisor.ts"() {
64250
+ "use strict";
64251
+ init_zod();
64252
+ init_schemas3();
64253
+ init_logger();
64254
+ RankingRowSchema = external_exports.object({
64255
+ runtime: external_exports.string().min(1).optional(),
64256
+ id: external_exports.string().min(1),
64257
+ eligible: external_exports.boolean(),
64258
+ reason: external_exports.string().trim().min(1),
64259
+ badge: external_exports.enum(["recommended", "reserved"]).optional()
64260
+ });
64261
+ RankingSchema = external_exports.object({
64262
+ accounts: external_exports.array(external_exports.unknown()),
64263
+ recommendedId: external_exports.string().nullable()
64264
+ });
64265
+ LimitedPlanSchema = external_exports.discriminatedUnion("mode", [
64266
+ external_exports.object({ mode: external_exports.literal("auto"), target: external_exports.string().min(1), delaySeconds: external_exports.number() }),
64267
+ external_exports.object({ mode: external_exports.literal("wait"), resumeAt: external_exports.iso.datetime({ offset: true }).optional() }),
64268
+ external_exports.object({ mode: external_exports.literal("ask") })
64269
+ ]);
64270
+ CarryOverSeedSchema = external_exports.object({
64271
+ seedContext: external_exports.string().min(1).max(SEED_CONTEXT_MAX_LENGTH),
64272
+ prompt: external_exports.string().min(1).optional()
64273
+ });
64274
+ }
64275
+ });
64276
+
64277
+ // ../../apps/server/src/services/core/usage/current-usage-store.ts
64278
+ var init_current_usage_store = __esm({
64279
+ "../../apps/server/src/services/core/usage/current-usage-store.ts"() {
64280
+ "use strict";
64281
+ }
64282
+ });
64283
+
64284
+ // ../../apps/server/src/services/core/usage/account-ranking.ts
64285
+ var init_account_ranking = __esm({
64286
+ "../../apps/server/src/services/core/usage/account-ranking.ts"() {
64287
+ "use strict";
64288
+ init_account_usage();
64289
+ init_account_advisor();
64290
+ init_config_manager();
64291
+ init_account_eligibility();
64292
+ init_current_usage_store();
64293
+ }
64294
+ });
64295
+
63679
64296
  // ../../apps/server/src/services/core/usage/runtime-accounts.ts
63680
64297
  import path29 from "node:path";
63681
64298
  function expandAccountPath(dir, home2) {
@@ -63711,6 +64328,9 @@ var init_claude_config_dir = __esm({
63711
64328
  init_config_manager();
63712
64329
  init_account_usage();
63713
64330
  init_claude_config_env_lock();
64331
+ init_canonical_directory();
64332
+ init_account_eligibility();
64333
+ init_account_ranking();
63714
64334
  init_runtime_accounts();
63715
64335
  }
63716
64336
  });
@@ -63760,6 +64380,33 @@ function defaultAccountColorRefusal(patch) {
63760
64380
  "runtimes.claudeCode.defaultAccountColor: must be a lowercase #rrggbb color, or null for the default."
63761
64381
  ];
63762
64382
  }
64383
+ function accountRulesRefusal(patch) {
64384
+ const runtimes = patch.runtimes;
64385
+ if (!isRecord(runtimes)) return null;
64386
+ const claudeCode = runtimes.claudeCode;
64387
+ if (!isRecord(claudeCode)) return null;
64388
+ const details = [];
64389
+ if ("defaultAccountOnlyProjects" in claudeCode && !StrictRootListSchema.safeParse(claudeCode.defaultAccountOnlyProjects).success) {
64390
+ details.push(
64391
+ "runtimes.claudeCode.defaultAccountOnlyProjects: must be a list of project folders, or null for any project."
64392
+ );
64393
+ }
64394
+ if ("projectAccounts" in claudeCode && !StrictProjectAccountsSchema.safeParse(claudeCode.projectAccounts).success) {
64395
+ details.push(
64396
+ 'runtimes.claudeCode.projectAccounts: each project folder must map to { "allow": [account ids] }.'
64397
+ );
64398
+ }
64399
+ if (Array.isArray(claudeCode.accounts)) {
64400
+ claudeCode.accounts.forEach((row, index2) => {
64401
+ if (!isRecord(row) || !("onlyProjects" in row)) return;
64402
+ if (StrictRootListSchema.safeParse(row.onlyProjects).success) return;
64403
+ details.push(
64404
+ `runtimes.claudeCode.accounts.${index2}.onlyProjects: must be a list of project folders, or null for any project.`
64405
+ );
64406
+ });
64407
+ }
64408
+ return details.length > 0 ? details : null;
64409
+ }
63763
64410
  function withReadableLabel(row) {
63764
64411
  return typeof row.label === "string" || row.label === null ? row : { ...row, label: null };
63765
64412
  }
@@ -63795,11 +64442,18 @@ function planClaudeAccountWrite(stored, patched, seen) {
63795
64442
  ).map(({ row }) => withReadableLabel(row));
63796
64443
  return { ok: true, accounts: [...merged, ...kept], unlisted };
63797
64444
  }
64445
+ var StrictRootListSchema, StrictProjectAccountsSchema;
63798
64446
  var init_claude_account_patch = __esm({
63799
64447
  "../../apps/server/src/services/core/operator/claude-account-patch.ts"() {
63800
64448
  "use strict";
64449
+ init_zod();
63801
64450
  init_account_usage();
63802
64451
  init_config_schema();
64452
+ StrictRootListSchema = external_exports.array(external_exports.string().min(1)).nullable();
64453
+ StrictProjectAccountsSchema = external_exports.record(
64454
+ external_exports.string().min(1),
64455
+ external_exports.object({ allow: external_exports.array(external_exports.string().min(1)) }).strict()
64456
+ );
63803
64457
  }
63804
64458
  });
63805
64459
 
@@ -63886,12 +64540,14 @@ function applyConfigPatch(patch) {
63886
64540
  const patchObj = taken.patch;
63887
64541
  const colorRefusal = defaultAccountColorRefusal(patchObj);
63888
64542
  if (colorRefusal) return { ok: false, error: "Validation failed", details: colorRefusal };
63889
- const current = configManager.getAll();
63890
- const merged = deepMerge(current, patchObj);
64543
+ const rulesRefusal = accountRulesRefusal(patchObj);
64544
+ if (rulesRefusal) return { ok: false, error: "Validation failed", details: rulesRefusal };
64545
+ const current2 = configManager.getAll();
64546
+ const merged = deepMerge(current2, patchObj);
63891
64547
  settleLegacyAccountAlias(merged, patchObj);
63892
64548
  const patchedClaude = patchObj.runtimes?.claudeCode;
63893
64549
  const namesAccounts = isPlainObject5(patchedClaude) && "accounts" in patchedClaude;
63894
- const storedAccounts = current.runtimes?.claudeCode?.accounts;
64550
+ const storedAccounts = current2.runtimes?.claudeCode?.accounts;
63895
64551
  const accountPlan = planClaudeAccountWrite(
63896
64552
  storedAccounts,
63897
64553
  namesAccounts ? patchedClaude.accounts : void 0,
@@ -63945,7 +64601,7 @@ function applyConfigPatch(patch) {
63945
64601
  configManager.set(configKey, validated[configKey]);
63946
64602
  }
63947
64603
  }
63948
- if (claudeAccountsChanged(current.runtimes, validated.runtimes)) {
64604
+ if (claudeAccountsChanged(current2.runtimes, validated.runtimes)) {
63949
64605
  if (applyClaudeAccountChange) {
63950
64606
  applyClaudeAccountChange();
63951
64607
  } else {
@@ -63954,7 +64610,7 @@ function applyConfigPatch(patch) {
63954
64610
  );
63955
64611
  }
63956
64612
  }
63957
- return { ok: true, before: current, config: configManager.getAll(), warnings };
64613
+ return { ok: true, before: current2, config: configManager.getAll(), warnings };
63958
64614
  }
63959
64615
  var DANGEROUS_KEYS, applyClaudeAccountChange, LOGGED_PATH_LIMIT, MAX_SEGMENT_CHARS, PLAIN_SEGMENT, RESIDUAL_UNSAFE;
63960
64616
  var init_config_patch = __esm({
@@ -63981,13 +64637,13 @@ function asRecord(value) {
63981
64637
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
63982
64638
  }
63983
64639
  function readPath2(patch, path53) {
63984
- let current = patch;
64640
+ let current2 = patch;
63985
64641
  for (const key of path53.split(".")) {
63986
- const record2 = asRecord(current);
64642
+ const record2 = asRecord(current2);
63987
64643
  if (!record2) return void 0;
63988
- current = record2[key];
64644
+ current2 = record2[key];
63989
64645
  }
63990
- return current;
64646
+ return current2;
63991
64647
  }
63992
64648
  function hasStandingAutonomyAck() {
63993
64649
  const ui = configManager?.get("ui");
@@ -64057,12 +64713,12 @@ __export(config_write_exports, {
64057
64713
  onTrustStopChange: () => onTrustStopChange
64058
64714
  });
64059
64715
  function leafAt(config3, path53) {
64060
- let current = config3;
64716
+ let current2 = config3;
64061
64717
  for (const key of path53) {
64062
- if (current === null || typeof current !== "object") return null;
64063
- current = current[key];
64718
+ if (current2 === null || typeof current2 !== "object") return null;
64719
+ current2 = current2[key];
64064
64720
  }
64065
- return typeof current === "string" ? current : null;
64721
+ return typeof current2 === "string" ? current2 : null;
64066
64722
  }
64067
64723
  function onTrustStopChange(listener) {
64068
64724
  trustStopListener = listener;
@@ -71066,7 +71722,7 @@ var init_src3 = __esm({
71066
71722
  });
71067
71723
 
71068
71724
  // ../harness/src/adopt/refusals.ts
71069
- function joinNames(items) {
71725
+ function joinNames2(items) {
71070
71726
  if (items.length <= 1) return items[0] ?? "";
71071
71727
  return `${items.slice(0, -1).join(", ")} and ${items[items.length - 1]}`;
71072
71728
  }
@@ -71081,7 +71737,7 @@ var init_refusals = __esm({
71081
71737
  CLAUDE_PLUGIN_ROOT = "${CLAUDE_PLUGIN_ROOT}";
71082
71738
  ADOPT_SENTENCES = {
71083
71739
  /** R1, and there is no such skill anywhere adopt looked. */
71084
- S2: (name, roots) => `There is no skill called "${name}" in ${joinNames([...roots])}. Run dorkos harness sync --check to see what is here.`,
71740
+ S2: (name, roots) => `There is no skill called "${name}" in ${joinNames2([...roots])}. Run dorkos harness sync --check to see what is here.`,
71085
71741
  /** R1, and the name is already in the canonical layer as well. */
71086
71742
  S2b: (name, source) => `"${name}" is already in .agents/skills, where every agent reads it. The copy in ${source} is a second one that gets in the way \u2014 delete one of them.`,
71087
71743
  /** R1, and the name is declared in `manifest.claudeOnlySkills`. */
@@ -71269,11 +71925,11 @@ function notOnAllowlistReason(name, verdict) {
71269
71925
  case "body-token":
71270
71926
  return ADOPT_SENTENCES.S7b(name);
71271
71927
  case "claude-field":
71272
- return ADOPT_SENTENCES.S7(name, joinNames(verdict.fields));
71928
+ return ADOPT_SENTENCES.S7(name, joinNames2(verdict.fields));
71273
71929
  case "dorkos-field":
71274
- return ADOPT_SENTENCES.S7d(name, joinNames(verdict.fields));
71930
+ return ADOPT_SENTENCES.S7d(name, joinNames2(verdict.fields));
71275
71931
  default:
71276
- return ADOPT_SENTENCES.S7c(name, joinNames(verdict.fields));
71932
+ return ADOPT_SENTENCES.S7c(name, joinNames2(verdict.fields));
71277
71933
  }
71278
71934
  }
71279
71935
  function declarationReason(verdict) {
@@ -71282,11 +71938,11 @@ function declarationReason(verdict) {
71282
71938
  case "body-token":
71283
71939
  return ADOPT_DECLARATION_REASONS.bodyToken();
71284
71940
  case "claude-field":
71285
- return ADOPT_DECLARATION_REASONS.claudeFields(joinNames(verdict.fields));
71941
+ return ADOPT_DECLARATION_REASONS.claudeFields(joinNames2(verdict.fields));
71286
71942
  case "dorkos-field":
71287
- return ADOPT_DECLARATION_REASONS.dorkosFields(joinNames(verdict.fields));
71943
+ return ADOPT_DECLARATION_REASONS.dorkosFields(joinNames2(verdict.fields));
71288
71944
  default:
71289
- return ADOPT_DECLARATION_REASONS.unknownFields(joinNames(verdict.fields));
71945
+ return ADOPT_DECLARATION_REASONS.unknownFields(joinNames2(verdict.fields));
71290
71946
  }
71291
71947
  }
71292
71948
  var CLAUDE_SKILLS_ROOT;
@@ -73101,7 +73757,7 @@ function harnessesThatCannotSee(root, enabled3) {
73101
73757
  function adoptableSentence(input4) {
73102
73758
  const { root, names, cannotSee, projectPath } = input4;
73103
73759
  if (names.length === 0 || cannotSee.length === 0) return "";
73104
- const tools = joinNames(cannotSee.map((harness) => HARNESS_LABELS[harness]));
73760
+ const tools = joinNames2(cannotSee.map((harness) => HARNESS_LABELS[harness]));
73105
73761
  const project2 = projectPath === void 0 ? "" : ` --project ${projectPath}`;
73106
73762
  if (names.length === 1) {
73107
73763
  return `1 skill lives only in ${root} and ${tools} cannot see it \u2014 dorkos harness adopt ${names[0]}${project2} moves it`;
@@ -73164,15 +73820,15 @@ function viaOf(root, abs) {
73164
73820
  function ascendLevels(root, cwd, stopAtWorktree) {
73165
73821
  const rel = relative7(root, cwd);
73166
73822
  const inside = rel === "" || !rel.startsWith("..") && !isAbsolute4(rel);
73167
- let current = inside ? cwd : root;
73823
+ let current2 = inside ? cwd : root;
73168
73824
  const levels2 = [];
73169
73825
  for (; ; ) {
73170
- levels2.push(current);
73171
- if (stopAtWorktree && existsSync13(join36(current, ".git"))) break;
73172
- if (current === root) break;
73173
- const parent = resolve6(current, "..");
73174
- if (parent === current) break;
73175
- current = parent;
73826
+ levels2.push(current2);
73827
+ if (stopAtWorktree && existsSync13(join36(current2, ".git"))) break;
73828
+ if (current2 === root) break;
73829
+ const parent = resolve6(current2, "..");
73830
+ if (parent === current2) break;
73831
+ current2 = parent;
73176
73832
  }
73177
73833
  return levels2;
73178
73834
  }
@@ -73569,7 +74225,7 @@ __export(src_exports, {
73569
74225
  isJunctionAt: () => isJunctionAt,
73570
74226
  isPathIgnored: () => isPathIgnored,
73571
74227
  isProjectScoped: () => isProjectScoped,
73572
- joinNames: () => joinNames,
74228
+ joinNames: () => joinNames2,
73573
74229
  junctionCommitWarnings: () => junctionCommitWarnings,
73574
74230
  listAuthoredSkills: () => listAuthoredSkills,
73575
74231
  listSkillDirs: () => listSkillDirs,
@@ -75081,9 +75737,9 @@ var init_marketplace_cache = __esm({
75081
75737
  async writeFetchStatus(marketplaceName, status) {
75082
75738
  const file2 = join45(this.marketplaceDir(marketplaceName), LAST_CHECK_FILENAME);
75083
75739
  await withFileLock(file2, async (write) => {
75084
- const current = await this.readFetchStatus(marketplaceName);
75085
- if (current && current.startedAt > status.startedAt) return;
75086
- const next = !status.ok && status.packageCount === void 0 && current?.packageCount !== void 0 ? { ...status, packageCount: current.packageCount } : status;
75740
+ const current2 = await this.readFetchStatus(marketplaceName);
75741
+ if (current2 && current2.startedAt > status.startedAt) return;
75742
+ const next = !status.ok && status.packageCount === void 0 && current2?.packageCount !== void 0 ? { ...status, packageCount: current2.packageCount } : status;
75087
75743
  await write(`${JSON.stringify(next)}
75088
75744
  `);
75089
75745
  });
@@ -78654,7 +79310,7 @@ async function runMarketplaceOutdated(args) {
78654
79310
  const outdated = result2.checks.filter((c3) => c3.status === "update-available");
78655
79311
  const linked = result2.checks.filter((c3) => c3.linked === true);
78656
79312
  const unknown2 = result2.checks.filter((c3) => c3.status === "unknown" && c3.linked !== true);
78657
- const current = result2.checks.filter((c3) => c3.status === "current");
79313
+ const current2 = result2.checks.filter((c3) => c3.status === "current");
78658
79314
  const code = outdated.length > 0 ? OUTDATED_EXIT.outdated : unknown2.length > 0 ? OUTDATED_EXIT.unknown : OUTDATED_EXIT.current;
78659
79315
  if (args.json) {
78660
79316
  printJson({ outdated, unknown: unknown2, linked });
@@ -78665,7 +79321,7 @@ async function runMarketplaceOutdated(args) {
78665
79321
  return code;
78666
79322
  }
78667
79323
  if (code === OUTDATED_EXIT.current && linked.length === 0) {
78668
- const n2 = current.length;
79324
+ const n2 = current2.length;
78669
79325
  console.log(`Everything is up to date (${n2} ${n2 === 1 ? "package" : "packages"} checked).`);
78670
79326
  return code;
78671
79327
  }
@@ -78694,7 +79350,7 @@ async function runMarketplaceOutdated(args) {
78694
79350
  unknown2.length > 0 && `${unknown2.length} could not be checked`,
78695
79351
  linked.length > 0 && `${linked.length} linked, not checked`
78696
79352
  ].filter(Boolean);
78697
- const rest = code === OUTDATED_EXIT.current ? ` Everything else is up to date (${current.length} checked).` : "";
79353
+ const rest = code === OUTDATED_EXIT.current ? ` Everything else is up to date (${current2.length} checked).` : "";
78698
79354
  const hint = outdated.length > 0 ? ` Run \`dorkos marketplace update --apply${args.projectPath ? ` --project ${shellWord(args.projectPath)}` : ""}\` to install ${outdated.length === 1 ? "it" : "them"}.` : "";
78699
79355
  console.log(`${parts.join(", ")}.${rest}${hint}`);
78700
79356
  return code;
@@ -79294,11 +79950,11 @@ function renderUpdateChecks(checks, apply) {
79294
79950
  if (check4.note) console.log(` ${check4.note}`);
79295
79951
  }
79296
79952
  const updates = checks.filter((c3) => c3.status === "update-available").length;
79297
- const current = checks.filter((c3) => c3.status === "current").length;
79953
+ const current2 = checks.filter((c3) => c3.status === "current").length;
79298
79954
  const unknown2 = checks.filter((c3) => c3.status === "unknown").length;
79299
79955
  const parts = [
79300
79956
  updates > 0 && `${updates} ${updates === 1 ? "update" : "updates"} available`,
79301
- current > 0 && `${current} up to date`,
79957
+ current2 > 0 && `${current2} up to date`,
79302
79958
  unknown2 > 0 && `${unknown2} could not be checked`
79303
79959
  ].filter(Boolean);
79304
79960
  const hint = !apply && updates > 0 ? ` Run again with --apply to install ${updates === 1 ? "it" : "them"}.` : "";
@@ -81543,7 +82199,7 @@ async function deployFlySecrets(options, appName) {
81543
82199
  const app = parseInput(ExternalIdentifierSchema, appName);
81544
82200
  return runProviderMutation({
81545
82201
  ...options,
81546
- args: ["secrets", "deploy", "--app", app, "--yes"],
82202
+ args: ["secrets", "deploy", "--app", app],
81547
82203
  parse: () => ({ operation: "deploy" })
81548
82204
  });
81549
82205
  }
@@ -81943,6 +82599,14 @@ var init_neon_mutate = __esm({
81943
82599
  });
81944
82600
 
81945
82601
  // src/commands/community-deploy/fly-graphql-contract.ts
82602
+ function tigrisCredentialsFromEnvironment(environment) {
82603
+ const parsed = TigrisEnvironmentSchema.safeParse(environment);
82604
+ if (!parsed.success) return null;
82605
+ return new TigrisBucketCredentials(
82606
+ parsed.data.AWS_ACCESS_KEY_ID,
82607
+ parsed.data.AWS_SECRET_ACCESS_KEY
82608
+ );
82609
+ }
81946
82610
  function invalidResponse() {
81947
82611
  return new FlyGraphqlContractError("INVALID_RESPONSE");
81948
82612
  }
@@ -81961,7 +82625,7 @@ function sanitizeAddOn(value) {
81961
82625
  providerName: addOn.addOnProvider.name,
81962
82626
  appId: addOn.app.id,
81963
82627
  appName: addOn.app.name,
81964
- public: addOn.options.public
82628
+ public: addOn.options?.public ?? false
81965
82629
  };
81966
82630
  }
81967
82631
  function parseTigrisTermsResponse(response) {
@@ -81981,17 +82645,48 @@ function parseTigrisCreateResponse(response) {
81981
82645
  } catch {
81982
82646
  throw invalidResponse();
81983
82647
  }
81984
- return sanitizeAddOn(parsed.data.createAddOn.addOn);
82648
+ const { environment, ...addOn } = parsed.data.createAddOn.addOn;
82649
+ return {
82650
+ identity: sanitizeAddOn(addOn),
82651
+ credentials: tigrisCredentialsFromEnvironment(environment)
82652
+ };
82653
+ }
82654
+ function parseTigrisCredentialsResponse(response, expectedId) {
82655
+ if (AddOnNotFoundEnvelopeSchema.safeParse(response).success) {
82656
+ throw new FlyGraphqlContractError("ADD_ON_MISSING");
82657
+ }
82658
+ let parsed;
82659
+ try {
82660
+ parsed = CredentialsEnvelopeSchema.parse(response);
82661
+ } catch {
82662
+ throw invalidResponse();
82663
+ }
82664
+ if (parsed.data.addOn.id !== expectedId) throw new FlyGraphqlContractError("BINDING_MISMATCH");
82665
+ return tigrisCredentialsFromEnvironment(parsed.data.addOn.environment);
81985
82666
  }
81986
82667
  function parseTigrisReadResponse(response) {
82668
+ if (AddOnNotFoundEnvelopeSchema.safeParse(response).success) {
82669
+ throw new FlyGraphqlContractError("ADD_ON_MISSING");
82670
+ }
81987
82671
  let parsed;
81988
82672
  try {
81989
82673
  parsed = ReadEnvelopeSchema.parse(response);
81990
82674
  } catch {
81991
82675
  throw invalidResponse();
81992
82676
  }
81993
- if (parsed.data.node === null) throw new FlyGraphqlContractError("ADD_ON_MISSING");
81994
- return sanitizeAddOn(parsed.data.node);
82677
+ return sanitizeAddOn(parsed.data.addOn);
82678
+ }
82679
+ function parseAppTigrisResponse(response, appName) {
82680
+ let parsed;
82681
+ try {
82682
+ parsed = AppTigrisEnvelopeSchema.parse(response);
82683
+ } catch {
82684
+ throw invalidResponse();
82685
+ }
82686
+ const { app } = parsed.data;
82687
+ if (app.name !== appName) throw new FlyGraphqlContractError("BINDING_MISMATCH");
82688
+ if (app.addOns.totalCount !== app.addOns.nodes.length) throw invalidResponse();
82689
+ return app.addOns.nodes.map(({ id, name }) => ({ id, name }));
81995
82690
  }
81996
82691
  function parseTigrisDeleteResponse(response, expectedName) {
81997
82692
  let parsed;
@@ -82022,7 +82717,7 @@ function createTigrisVariables(input4) {
82022
82717
  const parsed = CreateInputSchema.parse(input4);
82023
82718
  return { input: { ...parsed, type: "tigris" } };
82024
82719
  }
82025
- var SafeIdentifierSchema2, SafeStatusSchema, AddOnSchema, TermsEnvelopeSchema, CreateEnvelopeSchema, ReadEnvelopeSchema, DeleteEnvelopeSchema, ExpectedBindingSchema, CreateInputSchema, FLY_TIGRIS_TERMS_QUERY, FLY_TIGRIS_CREATE_MUTATION, FLY_TIGRIS_READ_QUERY, FLY_TIGRIS_DELETE_MUTATION, FlyGraphqlContractError;
82720
+ var SafeIdentifierSchema2, SafeStatusSchema, AddOnSchema, TermsEnvelopeSchema, CreateEnvelopeSchema, TigrisKeyValueSchema, TigrisEnvironmentSchema, CredentialsEnvelopeSchema, ReadEnvelopeSchema, AddOnNotFoundEnvelopeSchema, AppTigrisEnvelopeSchema, DeleteEnvelopeSchema, ExpectedBindingSchema, CreateInputSchema, FLY_TIGRIS_TERMS_QUERY, FLY_TIGRIS_CREATE_MUTATION, FLY_TIGRIS_CREDENTIALS_QUERY, FLY_APP_TIGRIS_QUERY, FLY_TIGRIS_READ_QUERY, FLY_TIGRIS_DELETE_MUTATION, FlyGraphqlContractError, TigrisBucketCredentials;
82026
82721
  var init_fly_graphql_contract = __esm({
82027
82722
  "src/commands/community-deploy/fly-graphql-contract.ts"() {
82028
82723
  "use strict";
@@ -82033,7 +82728,11 @@ var init_fly_graphql_contract = __esm({
82033
82728
  id: SafeIdentifierSchema2,
82034
82729
  name: SafeIdentifierSchema2,
82035
82730
  status: SafeStatusSchema,
82036
- options: external_exports.object({ public: external_exports.boolean() }).passthrough(),
82731
+ // Fly stores no options for a bucket created without them (as this launcher creates it) and
82732
+ // answers `options: null` (DOR-2559; `AddOn.options: JSON` is nullable in Fly's schema). That
82733
+ // is Fly's private default. The key must still be present, and a present `public` must be a
82734
+ // boolean, so only an explicit `public: true` reads as public.
82735
+ options: external_exports.object({ public: external_exports.boolean() }).passthrough().nullable(),
82037
82736
  organization: external_exports.object({ slug: SafeIdentifierSchema2 }).strict(),
82038
82737
  addOnProvider: external_exports.object({ name: SafeIdentifierSchema2 }).strict(),
82039
82738
  app: external_exports.object({ id: SafeIdentifierSchema2, name: SafeIdentifierSchema2 }).strict()
@@ -82044,10 +82743,46 @@ var init_fly_graphql_contract = __esm({
82044
82743
  }).strict()
82045
82744
  }).strict();
82046
82745
  CreateEnvelopeSchema = external_exports.object({
82047
- data: external_exports.object({ createAddOn: external_exports.object({ addOn: AddOnSchema }).strict() }).strict()
82746
+ data: external_exports.object({
82747
+ createAddOn: external_exports.object({ addOn: AddOnSchema.extend({ environment: external_exports.unknown().optional() }) }).strict()
82748
+ }).strict()
82749
+ }).strict();
82750
+ TigrisKeyValueSchema = external_exports.string().min(1).max(1024).regex(/^[\x21-\x7e]+$/u);
82751
+ TigrisEnvironmentSchema = external_exports.object({ AWS_ACCESS_KEY_ID: TigrisKeyValueSchema, AWS_SECRET_ACCESS_KEY: TigrisKeyValueSchema }).passthrough();
82752
+ CredentialsEnvelopeSchema = external_exports.object({
82753
+ data: external_exports.object({
82754
+ addOn: external_exports.object({ id: SafeIdentifierSchema2, environment: external_exports.unknown().optional() }).strict()
82755
+ }).strict()
82048
82756
  }).strict();
82049
82757
  ReadEnvelopeSchema = external_exports.object({
82050
- data: external_exports.object({ node: AddOnSchema.nullable() }).strict()
82758
+ // Fly's GraphQL has no Relay `node` root field; `addOn(id:)` is the exact-ID read (live gate,
82759
+ // DOR-2169, 2026-09-29: `node(id:)` answered only "Field 'node' doesn't exist on type 'Queries'").
82760
+ // Not nullable: a bare `addOn: null` without Fly's NOT_FOUND error is not proof the bucket is
82761
+ // gone, and treating it as gone once let cleanup skip a bucket that was still billing (DOR-2584
82762
+ // review). Only `AddOnNotFoundEnvelopeSchema` means missing.
82763
+ data: external_exports.object({ addOn: AddOnSchema }).strict()
82764
+ }).strict();
82765
+ AddOnNotFoundEnvelopeSchema = external_exports.object({
82766
+ data: external_exports.object({ addOn: external_exports.null() }).strict(),
82767
+ errors: external_exports.array(
82768
+ external_exports.object({
82769
+ path: external_exports.tuple([external_exports.literal("addOn")]),
82770
+ extensions: external_exports.object({ code: external_exports.literal("NOT_FOUND") }).passthrough()
82771
+ }).passthrough()
82772
+ ).min(1)
82773
+ }).strict();
82774
+ AppTigrisEnvelopeSchema = external_exports.object({
82775
+ data: external_exports.object({
82776
+ app: external_exports.object({
82777
+ name: SafeIdentifierSchema2,
82778
+ addOns: external_exports.object({
82779
+ totalCount: external_exports.number().int().nonnegative(),
82780
+ nodes: external_exports.array(
82781
+ external_exports.object({ id: SafeIdentifierSchema2, name: SafeIdentifierSchema2 }).strict()
82782
+ )
82783
+ }).strict()
82784
+ }).strict()
82785
+ }).strict()
82051
82786
  }).strict();
82052
82787
  DeleteEnvelopeSchema = external_exports.object({
82053
82788
  data: external_exports.object({
@@ -82085,25 +82820,43 @@ var init_fly_graphql_contract = __esm({
82085
82820
  name
82086
82821
  status
82087
82822
  options
82823
+ environment
82088
82824
  organization { slug }
82089
82825
  addOnProvider { name }
82090
82826
  app { id name }
82091
82827
  }
82092
82828
  }
82093
82829
  }
82830
+ `;
82831
+ FLY_TIGRIS_CREDENTIALS_QUERY = `
82832
+ query DorkosReadTigrisCredentials($id: ID!) {
82833
+ addOn(id: $id) {
82834
+ id
82835
+ environment
82836
+ }
82837
+ }
82838
+ `;
82839
+ FLY_APP_TIGRIS_QUERY = `
82840
+ query DorkosListAppTigris($appName: String!) {
82841
+ app(name: $appName) {
82842
+ name
82843
+ addOns(type: tigris, first: 50) {
82844
+ totalCount
82845
+ nodes { id name }
82846
+ }
82847
+ }
82848
+ }
82094
82849
  `;
82095
82850
  FLY_TIGRIS_READ_QUERY = `
82096
82851
  query DorkosReadTigris($id: ID!) {
82097
- node(id: $id) {
82098
- ... on AddOn {
82099
- id
82100
- name
82101
- status
82102
- options
82103
- organization { slug }
82104
- addOnProvider { name }
82105
- app { id name }
82106
- }
82852
+ addOn(id: $id) {
82853
+ id
82854
+ name
82855
+ status
82856
+ options
82857
+ organization { slug }
82858
+ addOnProvider { name }
82859
+ app { id name }
82107
82860
  }
82108
82861
  }
82109
82862
  `;
@@ -82128,6 +82881,40 @@ var init_fly_graphql_contract = __esm({
82128
82881
  this.code = code;
82129
82882
  }
82130
82883
  };
82884
+ TigrisBucketCredentials = class {
82885
+ #values;
82886
+ /**
82887
+ * Wrap validated keys without exposing them as object data.
82888
+ *
82889
+ * @param accessKeyId - The bucket's access key id.
82890
+ * @param secretAccessKey - The bucket's secret access key.
82891
+ */
82892
+ constructor(accessKeyId, secretAccessKey) {
82893
+ this.#values = { AWS_ACCESS_KEY_ID: accessKeyId, AWS_SECRET_ACCESS_KEY: secretAccessKey };
82894
+ }
82895
+ /**
82896
+ * Use the keys, by their app secret names, inside one bounded callback.
82897
+ *
82898
+ * @param consumer - The secret-staging call.
82899
+ * @returns The consumer result.
82900
+ */
82901
+ async use(consumer) {
82902
+ if (!this.#values) throw new FlyGraphqlContractError("INVALID_RESPONSE");
82903
+ return consumer(this.#values);
82904
+ }
82905
+ /** Drop this wrapper's reference to the keys. */
82906
+ dispose() {
82907
+ this.#values = void 0;
82908
+ }
82909
+ /** Return a safe marker for string interpolation. */
82910
+ toString() {
82911
+ return "[REDACTED Tigris bucket credentials]";
82912
+ }
82913
+ /** Return a safe marker for JSON serialization. */
82914
+ toJSON() {
82915
+ return "[REDACTED Tigris bucket credentials]";
82916
+ }
82917
+ };
82131
82918
  }
82132
82919
  });
82133
82920
 
@@ -82253,6 +83040,7 @@ var init_fly_graphql_client = __esm({
82253
83040
  * the mutation. The caller must inspect by provider-issued provenance and must not retry blindly.
82254
83041
  *
82255
83042
  * @param input - Validated creation identity selected by the consented plan.
83043
+ * @returns The bucket's identity, and its access keys when Fly sent them (in memory only).
82256
83044
  */
82257
83045
  async createTigris(input4) {
82258
83046
  let variables;
@@ -82273,6 +83061,40 @@ var init_fly_graphql_client = __esm({
82273
83061
  }
82274
83062
  return this.request(FLY_TIGRIS_READ_QUERY, { id: addOnId }, parseTigrisReadResponse, false);
82275
83063
  }
83064
+ /**
83065
+ * Read one bucket's access keys by its exact ID, for a resumed launch that has none in memory.
83066
+ *
83067
+ * @param addOnId - Provider-issued add-on ID already recorded in the launch journal.
83068
+ * @returns Redacting credentials, or null when Fly returned none.
83069
+ */
83070
+ async readTigrisCredentials(addOnId) {
83071
+ if (!SAFE_PROVIDER_IDENTIFIER_PATTERN.test(addOnId)) {
83072
+ throw new FlyGraphqlClientError("INVALID_RESPONSE");
83073
+ }
83074
+ return this.request(
83075
+ FLY_TIGRIS_CREDENTIALS_QUERY,
83076
+ { id: addOnId },
83077
+ (response) => parseTigrisCredentialsResponse(response, addOnId),
83078
+ false
83079
+ );
83080
+ }
83081
+ /**
83082
+ * List every Tigris bucket attached to one app, by id and name.
83083
+ *
83084
+ * @param appName - The exact app name.
83085
+ * @returns The attached buckets; an empty list means the app has none.
83086
+ */
83087
+ async listTigrisOnApp(appName) {
83088
+ if (!SAFE_PROVIDER_IDENTIFIER_PATTERN.test(appName)) {
83089
+ throw new FlyGraphqlClientError("INVALID_RESPONSE");
83090
+ }
83091
+ return this.request(
83092
+ FLY_APP_TIGRIS_QUERY,
83093
+ { appName },
83094
+ (response) => parseAppTigrisResponse(response, appName),
83095
+ false
83096
+ );
83097
+ }
82276
83098
  /** Delete one exact Tigris name after the caller independently reverified its journal binding. */
82277
83099
  async deleteTigris(addOnName) {
82278
83100
  if (!SAFE_PROVIDER_IDENTIFIER_PATTERN.test(addOnName)) {
@@ -82646,6 +83468,31 @@ function tigrisIdentity(identity, plan, app) {
82646
83468
  bindingId: verified.appId
82647
83469
  };
82648
83470
  }
83471
+ async function stageTigrisKeys(options, appName, credentials) {
83472
+ try {
83473
+ await credentials.use((values2) => stageFlySecrets(options.fly, appName, values2));
83474
+ } finally {
83475
+ credentials.dispose();
83476
+ }
83477
+ }
83478
+ async function ensureTigrisSecrets(options, appName, addOnId) {
83479
+ const before = await readFlySecretInventory(options.fly, appName);
83480
+ const present = EXPECTED_TIGRIS_SECRET_NAMES.filter(
83481
+ (name) => before.some((item) => item.name === name)
83482
+ );
83483
+ if (present.length === EXPECTED_TIGRIS_SECRET_NAMES.length) {
83484
+ verifyTigrisSecretNames(before);
83485
+ return;
83486
+ }
83487
+ if (present.length > 0) throw new TigrisSessionError("MISSING_TIGRIS_SECRETS");
83488
+ const credentials = await useTigrisClient(
83489
+ options,
83490
+ (client2) => client2.readTigrisCredentials(addOnId)
83491
+ );
83492
+ if (!credentials) throw new TigrisSessionError("MISSING_TIGRIS_SECRETS");
83493
+ await stageTigrisKeys(options, appName, credentials);
83494
+ verifyTigrisSecretNames(await readFlySecretInventory(options.fly, appName));
83495
+ }
82649
83496
  function createDefaultCommunityCreationDependencies(input4) {
82650
83497
  const app = async () => {
82651
83498
  const id = input4.latestJournal().resources.flyAppId;
@@ -82653,6 +83500,7 @@ function createDefaultCommunityCreationDependencies(input4) {
82653
83500
  return exactFlyApp(input4.options, input4.plan.fly.organizationId, id, input4.plan.fly.appName);
82654
83501
  };
82655
83502
  let flyOrganizationId;
83503
+ let tigrisCredentials = null;
82656
83504
  return {
82657
83505
  persist: input4.persist,
82658
83506
  now: input4.now,
@@ -82733,16 +83581,20 @@ function createDefaultCommunityCreationDependencies(input4) {
82733
83581
  primaryRegion: input4.plan.fly.region
82734
83582
  })
82735
83583
  );
82736
- const result2 = tigrisIdentity(created, input4.plan, exactApp);
82737
- return result2;
83584
+ tigrisCredentials?.dispose();
83585
+ tigrisCredentials = created.credentials;
83586
+ return tigrisIdentity(created.identity, input4.plan, exactApp);
82738
83587
  },
82739
83588
  inspect: async (id) => {
83589
+ const held2 = tigrisCredentials;
83590
+ tigrisCredentials = null;
83591
+ if (held2) {
83592
+ await stageTigrisKeys(input4.options, input4.plan.fly.appName, held2).catch(() => void 0);
83593
+ }
82740
83594
  const exactApp = await app();
82741
83595
  const found = await useTigrisClient(input4.options, (client2) => client2.readTigris(id));
82742
83596
  const result2 = tigrisIdentity(found, input4.plan, exactApp);
82743
- verifyTigrisSecretNames(
82744
- await readFlySecretInventory(input4.options.fly, input4.plan.fly.appName)
82745
- );
83597
+ await ensureTigrisSecrets(input4.options, input4.plan.fly.appName, found.addOnId);
82746
83598
  return result2;
82747
83599
  }
82748
83600
  }
@@ -83192,9 +84044,9 @@ function assertIdentity(step, identity, expectedBindingId) {
83192
84044
  throw new ProviderMutationError("INVALID_RESPONSE");
83193
84045
  }
83194
84046
  }
83195
- async function persistNext(dependencies, current, update) {
83196
- const next = withRevision(current, dependencies.now(), update);
83197
- await dependencies.persist(next, current.revision);
84047
+ async function persistNext(dependencies, current2, update) {
84048
+ const next = withRevision(current2, dependencies.now(), update);
84049
+ await dependencies.persist(next, current2.revision);
83198
84050
  return next;
83199
84051
  }
83200
84052
  async function executeCreationStep(journal, step, dependencies) {
@@ -83213,11 +84065,11 @@ async function executeCreationStep(journal, step, dependencies) {
83213
84065
  if (journal.pendingIntent && (!existingId || journal.pendingIntent.provider !== step.service)) {
83214
84066
  throw new CommunityCreationUncertainError(journal.pendingIntent.provider);
83215
84067
  }
83216
- let current = journal;
84068
+ let current2 = journal;
83217
84069
  let createdId = existingId;
83218
84070
  if (!journal.pendingIntent) {
83219
84071
  await step.boundary.prepare?.();
83220
- current = await persistNext(dependencies, journal, {
84072
+ current2 = await persistNext(dependencies, journal, {
83221
84073
  pendingIntent: {
83222
84074
  provider: step.service,
83223
84075
  organizationId: step.organizationId,
@@ -83232,18 +84084,18 @@ async function executeCreationStep(journal, step, dependencies) {
83232
84084
  } catch (error63) {
83233
84085
  const safeCode = safeErrorCode(error63);
83234
84086
  if (isCertifiedPreSubmitFailure(safeCode)) {
83235
- await persistNext(dependencies, current, {
84087
+ await persistNext(dependencies, current2, {
83236
84088
  pendingIntent: null,
83237
84089
  lastSafeError: { category: safeErrorCategory(safeCode), code: safeCode }
83238
84090
  });
83239
84091
  throw error63;
83240
84092
  }
83241
- await persistUncertain(dependencies, current);
84093
+ await persistUncertain(dependencies, current2);
83242
84094
  throw new CommunityCreationUncertainError(step.service);
83243
84095
  }
83244
84096
  createdId = created.id;
83245
- current = await persistNext(dependencies, current, {
83246
- resources: { ...current.resources, [step.resourceKey]: createdId }
84097
+ current2 = await persistNext(dependencies, current2, {
84098
+ resources: { ...current2.resources, [step.resourceKey]: createdId }
83247
84099
  });
83248
84100
  }
83249
84101
  let inspected;
@@ -83251,26 +84103,32 @@ async function executeCreationStep(journal, step, dependencies) {
83251
84103
  inspected = await step.boundary.inspect(createdId);
83252
84104
  assertIdentity(step, inspected, expectedBindingId);
83253
84105
  if (inspected.id !== createdId) throw new ProviderMutationError("INVALID_RESPONSE");
83254
- } catch {
83255
- await persistUncertain(dependencies, current);
84106
+ } catch (error63) {
84107
+ if (step.service === "tigris" && safeErrorCode(error63) === "MISSING_TIGRIS_SECRETS") {
84108
+ await persistNext(dependencies, current2, {
84109
+ lastSafeError: { category: "invalid-response", code: "MISSING_TIGRIS_SECRETS" }
84110
+ });
84111
+ throw error63;
84112
+ }
84113
+ await persistUncertain(dependencies, current2);
83256
84114
  throw new CommunityCreationUncertainError(step.service);
83257
84115
  }
83258
- return persistNext(dependencies, current, {
84116
+ return persistNext(dependencies, current2, {
83259
84117
  state: step.state,
83260
84118
  pendingIntent: null,
83261
84119
  resources: {
83262
- ...current.resources,
84120
+ ...current2.resources,
83263
84121
  [step.resourceKey]: inspected.id,
83264
84122
  ...inspected.relatedResources ?? {}
83265
84123
  },
83266
84124
  verifiedBindings: [
83267
- ...current.verifiedBindings,
84125
+ ...current2.verifiedBindings,
83268
84126
  ...expectedBindingId === void 0 ? [] : [
83269
84127
  { kind: "bucket-to-app", sourceId: inspected.id, targetId: expectedBindingId }
83270
84128
  ],
83271
84129
  ...inspected.verifiedBindings ?? []
83272
84130
  ],
83273
- completedSteps: [...current.completedSteps, step.state],
84131
+ completedSteps: [...current2.completedSteps, step.state],
83274
84132
  lastSafeError: null
83275
84133
  });
83276
84134
  }
@@ -83283,8 +84141,8 @@ function isCertifiedPreSubmitFailure(code) {
83283
84141
  function safeErrorCategory(code) {
83284
84142
  return code === "AUTH_REQUIRED" ? "authentication" : code === "ACCESS_DENIED" || code === "TERMS_NOT_ACCEPTED" ? "authorization" : "transient";
83285
84143
  }
83286
- async function persistUncertain(dependencies, current) {
83287
- await persistNext(dependencies, current, {
84144
+ async function persistUncertain(dependencies, current2) {
84145
+ await persistNext(dependencies, current2, {
83288
84146
  state: "uncertain",
83289
84147
  lastSafeError: { category: "uncertain", code: "CREATION_OUTCOME_UNCERTAIN" }
83290
84148
  });
@@ -83311,7 +84169,7 @@ function assertJournalIdentity(journal, step, inspected, expectedBindingId) {
83311
84169
  }
83312
84170
  }
83313
84171
  async function executeCommunityCreationPhase(plan, journal, dependencies) {
83314
- let current = journal;
84172
+ let current2 = journal;
83315
84173
  const steps = [
83316
84174
  {
83317
84175
  service: "fly",
@@ -83342,9 +84200,9 @@ async function executeCommunityCreationPhase(plan, journal, dependencies) {
83342
84200
  ];
83343
84201
  for (const step of steps) {
83344
84202
  dependencies.progress?.(step.service);
83345
- current = await executeCreationStep(current, step, dependencies);
84203
+ current2 = await executeCreationStep(current2, step, dependencies);
83346
84204
  }
83347
- return current;
84205
+ return current2;
83348
84206
  }
83349
84207
  var CommunityCreationUncertainError;
83350
84208
  var init_execute = __esm({
@@ -83366,12 +84224,12 @@ var init_execute = __esm({
83366
84224
 
83367
84225
  // src/commands/community-deploy/deploy.ts
83368
84226
  import { randomBytes as randomBytes2 } from "node:crypto";
83369
- function nextJournal(current, now2, update) {
83370
- return { ...current, ...update, revision: current.revision + 1, updatedAt: now2 };
84227
+ function nextJournal(current2, now2, update) {
84228
+ return { ...current2, ...update, revision: current2.revision + 1, updatedAt: now2 };
83371
84229
  }
83372
- async function persist(dependencies, current, update) {
83373
- const next = nextJournal(current, dependencies.now(), update);
83374
- await dependencies.persist(next, current.revision);
84230
+ async function persist(dependencies, current2, update) {
84231
+ const next = nextJournal(current2, dependencies.now(), update);
84232
+ await dependencies.persist(next, current2.revision);
83375
84233
  return next;
83376
84234
  }
83377
84235
  function runtimeSecretRows(inventory) {
@@ -83413,33 +84271,33 @@ function runtimeEvidence(inventory) {
83413
84271
  return { machine, release };
83414
84272
  }
83415
84273
  async function executeCommunityDeployPhase(plan, journal, dependencies) {
83416
- let current = journal;
84274
+ let current2 = journal;
83417
84275
  let bootstrapSecret = null;
83418
- if (!current.completedSteps.includes("secrets_staged")) {
83419
- if (!current.secretBaseline) {
84276
+ if (!current2.completedSteps.includes("secrets_staged")) {
84277
+ if (!current2.secretBaseline) {
83420
84278
  const before = await dependencies.readSecrets();
83421
84279
  if (runtimeSecretRows(before).length > 0) {
83422
- await persist(dependencies, current, {
84280
+ await persist(dependencies, current2, {
83423
84281
  state: "uncertain",
83424
84282
  lastSafeError: { category: "uncertain", code: "CREATION_OUTCOME_UNCERTAIN" }
83425
84283
  });
83426
84284
  throw new Error("Runtime secrets exist without a proven journal checkpoint");
83427
84285
  }
83428
- current = await persist(dependencies, current, {
84286
+ current2 = await persist(dependencies, current2, {
83429
84287
  secretBaseline: runtimeDigestMap(before),
83430
84288
  lastSafeError: null
83431
84289
  });
83432
84290
  }
83433
- const baseline = current.secretBaseline;
84291
+ const baseline = current2.secretBaseline;
83434
84292
  if (!baseline) throw new ProviderMutationError("INVALID_RESPONSE");
83435
84293
  const observed = await dependencies.readSecrets();
83436
84294
  const observedRuntime = runtimeSecretRows(observed);
83437
84295
  if (observedRuntime.length > 0) {
83438
84296
  const staged = provesFreshStage(observed, baseline);
83439
- current = await persist(dependencies, current, {
84297
+ current2 = await persist(dependencies, current2, {
83440
84298
  state: "secrets_staged",
83441
84299
  secretDigests: staged,
83442
- completedSteps: [...current.completedSteps, "secrets_staged"],
84300
+ completedSteps: [...current2.completedSteps, "secrets_staged"],
83443
84301
  lastSafeError: null
83444
84302
  });
83445
84303
  } else {
@@ -83456,10 +84314,10 @@ async function executeCommunityDeployPhase(plan, journal, dependencies) {
83456
84314
  try {
83457
84315
  const staged = provesFreshStage(await dependencies.readSecrets(), baseline);
83458
84316
  bootstrapSecret = secretSet.bootstrapSecret();
83459
- current = await persist(dependencies, current, {
84317
+ current2 = await persist(dependencies, current2, {
83460
84318
  state: "secrets_staged",
83461
84319
  secretDigests: staged,
83462
- completedSteps: [...current.completedSteps, "secrets_staged"],
84320
+ completedSteps: [...current2.completedSteps, "secrets_staged"],
83463
84321
  lastSafeError: null
83464
84322
  });
83465
84323
  } finally {
@@ -83467,11 +84325,11 @@ async function executeCommunityDeployPhase(plan, journal, dependencies) {
83467
84325
  }
83468
84326
  }
83469
84327
  }
83470
- const expectedDigests = current.secretDigests ?? {};
84328
+ const expectedDigests = current2.secretDigests ?? {};
83471
84329
  if (Object.keys(expectedDigests).length !== COMMUNITY_RUNTIME_SECRET_NAMES.length) {
83472
84330
  throw new ProviderMutationError("INVALID_RESPONSE");
83473
84331
  }
83474
- if (!current.completedSteps.includes("deployed")) {
84332
+ if (!current2.completedSteps.includes("deployed")) {
83475
84333
  const existingSecrets = await dependencies.readSecrets();
83476
84334
  const deployedRows = runtimeSecretRows(existingSecrets);
83477
84335
  let inventory;
@@ -83493,15 +84351,15 @@ async function executeCommunityDeployPhase(plan, journal, dependencies) {
83493
84351
  inventory = dependencies.verifyNewRuntime(await dependencies.readRuntime(), previous);
83494
84352
  }
83495
84353
  const { machine, release } = runtimeEvidence(inventory);
83496
- current = await persist(dependencies, current, {
84354
+ current2 = await persist(dependencies, current2, {
83497
84355
  state: "deployed",
83498
84356
  resources: {
83499
- ...current.resources,
84357
+ ...current2.resources,
83500
84358
  flyMachineId: machine.id,
83501
84359
  flyReleaseId: release.id
83502
84360
  },
83503
84361
  verifiedBindings: [
83504
- ...current.verifiedBindings,
84362
+ ...current2.verifiedBindings,
83505
84363
  { kind: "machine-to-release", sourceId: machine.id, targetId: release.id },
83506
84364
  ...Object.values(expectedDigests).map((digest2) => ({
83507
84365
  kind: "secret-version-to-machine",
@@ -83509,19 +84367,19 @@ async function executeCommunityDeployPhase(plan, journal, dependencies) {
83509
84367
  targetId: machine.id
83510
84368
  }))
83511
84369
  ],
83512
- completedSteps: [...current.completedSteps, "deployed"],
84370
+ completedSteps: [...current2.completedSteps, "deployed"],
83513
84371
  lastSafeError: null
83514
84372
  });
83515
84373
  }
83516
- if (!current.completedSteps.includes("healthy")) {
84374
+ if (!current2.completedSteps.includes("healthy")) {
83517
84375
  await dependencies.verifyHealth(`https://${plan.fly.appName}.fly.dev`);
83518
- current = await persist(dependencies, current, {
84376
+ current2 = await persist(dependencies, current2, {
83519
84377
  state: "healthy",
83520
- completedSteps: [...current.completedSteps, "healthy"],
84378
+ completedSteps: [...current2.completedSteps, "healthy"],
83521
84379
  lastSafeError: null
83522
84380
  });
83523
84381
  }
83524
- return { journal: current, bootstrapSecret };
84382
+ return { journal: current2, bootstrapSecret };
83525
84383
  }
83526
84384
  var COMMUNITY_RUNTIME_SECRET_NAMES, CommunityRuntimeSecrets;
83527
84385
  var init_deploy = __esm({
@@ -83576,12 +84434,12 @@ var init_deploy = __esm({
83576
84434
 
83577
84435
  // src/commands/community-deploy/owner.ts
83578
84436
  import { randomBytes as randomBytes3 } from "node:crypto";
83579
- function nextJournal2(current, now2, update) {
83580
- return { ...current, ...update, revision: current.revision + 1, updatedAt: now2 };
84437
+ function nextJournal2(current2, now2, update) {
84438
+ return { ...current2, ...update, revision: current2.revision + 1, updatedAt: now2 };
83581
84439
  }
83582
- async function persist2(dependencies, current, update) {
83583
- const next = nextJournal2(current, dependencies.now(), update);
83584
- await dependencies.persist(next, current.revision);
84440
+ async function persist2(dependencies, current2, update) {
84441
+ const next = nextJournal2(current2, dependencies.now(), update);
84442
+ await dependencies.persist(next, current2.revision);
83585
84443
  return next;
83586
84444
  }
83587
84445
  function bootstrapDigest(inventory, status) {
@@ -83602,50 +84460,50 @@ async function replaceAndApplyBootstrap(journal, dependencies, ownerClaimed = fa
83602
84460
  const deployedDigest = bootstrapDigest(await dependencies.readSecrets(), "Deployed");
83603
84461
  if (deployedDigest !== stagedDigest) throw new ProviderMutationError("INVALID_RESPONSE");
83604
84462
  await dependencies.verifyRuntimeAndHealth();
83605
- const current = await persist2(dependencies, journal, {
84463
+ const current2 = await persist2(dependencies, journal, {
83606
84464
  secretDigests: { ...journal.secretDigests, [BOOTSTRAP_SECRET_NAME]: deployedDigest },
83607
84465
  ...ownerClaimed ? { ownerBootstrapRotated: true } : {},
83608
84466
  lastSafeError: null
83609
84467
  });
83610
- return { journal: current, secret };
84468
+ return { journal: current2, secret };
83611
84469
  }
83612
84470
  async function executeCommunityOwnerHandoff(plan, journal, initialBootstrapSecret, dependencies) {
83613
84471
  if (journal.completedSteps.includes("complete")) return journal;
83614
- let current = journal;
84472
+ let current2 = journal;
83615
84473
  const origin = `https://${plan.fly.appName}.fly.dev`;
83616
84474
  let handoffSecret = initialBootstrapSecret;
83617
- if (current.completedSteps.includes("owner_pending") && !await dependencies.ownerExists(origin)) {
84475
+ if (current2.completedSteps.includes("owner_pending") && !await dependencies.ownerExists(origin)) {
83618
84476
  if (!handoffSecret) {
83619
- const replacement = await replaceAndApplyBootstrap(current, dependencies);
83620
- current = replacement.journal;
84477
+ const replacement = await replaceAndApplyBootstrap(current2, dependencies);
84478
+ current2 = replacement.journal;
83621
84479
  handoffSecret = replacement.secret;
83622
84480
  }
83623
84481
  await dependencies.handoffSecret(origin, handoffSecret);
83624
84482
  }
83625
- if (!current.completedSteps.includes("owner_pending")) {
84483
+ if (!current2.completedSteps.includes("owner_pending")) {
83626
84484
  if (!handoffSecret) {
83627
- const replacement = await replaceAndApplyBootstrap(current, dependencies);
83628
- current = replacement.journal;
84485
+ const replacement = await replaceAndApplyBootstrap(current2, dependencies);
84486
+ current2 = replacement.journal;
83629
84487
  handoffSecret = replacement.secret;
83630
84488
  }
83631
84489
  await dependencies.handoffSecret(origin, handoffSecret);
83632
- current = await persist2(dependencies, current, {
84490
+ current2 = await persist2(dependencies, current2, {
83633
84491
  state: "owner_pending",
83634
- completedSteps: [...current.completedSteps, "owner_pending"],
84492
+ completedSteps: [...current2.completedSteps, "owner_pending"],
83635
84493
  lastSafeError: null
83636
84494
  });
83637
84495
  }
83638
84496
  if (!await dependencies.ownerExists(origin) && !await dependencies.waitForOwnerClaim(origin)) {
83639
- return current;
84497
+ return current2;
83640
84498
  }
83641
- if (!current.ownerBootstrapRotated) {
83642
- const rotation = await replaceAndApplyBootstrap(current, dependencies, true);
83643
- current = rotation.journal;
84499
+ if (!current2.ownerBootstrapRotated) {
84500
+ const rotation = await replaceAndApplyBootstrap(current2, dependencies, true);
84501
+ current2 = rotation.journal;
83644
84502
  }
83645
- if (!await dependencies.confirmAcceptance(origin)) return current;
83646
- return persist2(dependencies, current, {
84503
+ if (!await dependencies.confirmAcceptance(origin)) return current2;
84504
+ return persist2(dependencies, current2, {
83647
84505
  state: "complete",
83648
- completedSteps: [...current.completedSteps, "complete"],
84506
+ completedSteps: [...current2.completedSteps, "complete"],
83649
84507
  lastSafeError: null
83650
84508
  });
83651
84509
  }
@@ -83839,8 +84697,8 @@ async function writeLaunchJournal(filePath, journal, expectedRevision) {
83839
84697
  await withFileLock(
83840
84698
  filePath,
83841
84699
  () => withCrossProcessLock(filePath, async () => {
83842
- const current = await readLaunchJournal(filePath);
83843
- const actualRevision = current?.revision ?? null;
84700
+ const current2 = await readLaunchJournal(filePath);
84701
+ const actualRevision = current2?.revision ?? null;
83844
84702
  if (actualRevision !== expectedRevision) {
83845
84703
  throw new LaunchJournalConflictError(expectedRevision, actualRevision);
83846
84704
  }
@@ -84131,7 +84989,16 @@ function formatCommunityRecovery(journal) {
84131
84989
  Console: https://fly.io/apps/${selection.appName}` : ` Tigris bucket ${journal.resources.tigrisBucketId} \u2014 saved owner unavailable; may incur charges; private files may exist.` : null
84132
84990
  ].filter((row) => row !== null);
84133
84991
  const pending = journal.pendingIntent;
84134
- const reconciliation = pending ? pending.provider === "fly" ? `Unresolved Fly creation intent for ${pending.resourceName} in ${pending.organizationId}. Do not create or adopt a name match. Inspect: fly apps list --org ${pending.organizationId} --json
84992
+ const tigrisKeysMissing = pending?.provider === "tigris" && journal.resources.tigrisBucketId !== void 0 && journal.lastSafeError?.code === "MISSING_TIGRIS_SECRETS";
84993
+ const reconciliation = tigrisKeysMissing ? selection ? [
84994
+ `Tigris bucket ${selection.bucketName} exists, but its access keys are not on app ${selection.appName}, and Fly would not return them again. Keep this bucket; setup must not create another.`,
84995
+ `1. Open the bucket's Tigris console: fly storage dashboard ${selection.bucketName} --app ${selection.appName}`,
84996
+ `2. Create an access key there with read and write access to ${selection.bucketName}.`,
84997
+ `3. Run: fly secrets import --app ${selection.appName} --stage`,
84998
+ " then type two lines, AWS_ACCESS_KEY_ID=<key id> and AWS_SECRET_ACCESS_KEY=<secret>, and press Ctrl-D.",
84999
+ " (Typing them keeps the secret out of your shell history.)",
85000
+ "4. Resume with the command below."
85001
+ ].join("\n") : `Tigris bucket ${journal.resources.tigrisBucketId} exists, but its access keys are not on the app. Add AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY with fly secrets import --stage, then resume.` : pending ? pending.provider === "fly" ? `Unresolved Fly creation intent for ${pending.resourceName} in ${pending.organizationId}. Do not create or adopt a name match. Inspect: fly apps list --org ${pending.organizationId} --json
84135
85002
  Console: https://fly.io/dashboard/${pending.organizationId}` : pending.provider === "neon" ? `Unresolved Neon creation intent for ${pending.resourceName} in ${pending.organizationId}. Do not create or adopt a name match. Inspect: neonctl projects list --org-id ${pending.organizationId} --output json
84136
85003
  Console: https://console.neon.tech` : `Unresolved Tigris creation intent for ${pending.resourceName} in ${pending.organizationId}. Do not create or adopt a name match. Inspect: fly storage list --org ${pending.organizationId}
84137
85004
  Console: https://fly.io/dashboard/${pending.organizationId}` : null;
@@ -88641,7 +89508,7 @@ function createRemoteJWKSet(url2, options) {
88641
89508
  }
88642
89509
  const reload = async () => {
88643
89510
  if (pendingFetch && isCloudflareWorkers() && (pendingFetch = void 0), !pendingFetch) {
88644
- const sequence = ++reloadSequence, current = pendingFetch = fetchJwks(href, headers, AbortSignal.timeout(timeoutDuration), fetchImpl).then((json3) => {
89511
+ const sequence = ++reloadSequence, current2 = pendingFetch = fetchJwks(href, headers, AbortSignal.timeout(timeoutDuration), fetchImpl).then((json3) => {
88645
89512
  const next = createLocalJWKSet(json3);
88646
89513
  if (sequence <= appliedSequence)
88647
89514
  return;
@@ -88649,7 +89516,7 @@ function createRemoteJWKSet(url2, options) {
88649
89516
  const updatedAt = Date.now();
88650
89517
  cache3 && (cache3.uat = updatedAt, cache3.jwks = json3), jwksTimestamp = updatedAt, appliedSequence = sequence;
88651
89518
  }).finally(() => {
88652
- pendingFetch === current && (pendingFetch = void 0);
89519
+ pendingFetch === current2 && (pendingFetch = void 0);
88653
89520
  });
88654
89521
  }
88655
89522
  await pendingFetch;
@@ -95493,11 +96360,11 @@ var init_internal_adapter = __esm({
95493
96360
  async function withVerificationConsumeLock(key, fn) {
95494
96361
  const previous = verificationConsumeLocks.get(key) ?? Promise.resolve();
95495
96362
  let release;
95496
- const current = new Promise((resolve11) => {
96363
+ const current2 = new Promise((resolve11) => {
95497
96364
  release = resolve11;
95498
96365
  });
95499
96366
  const next = previous.catch(() => {
95500
- }).then(() => current);
96367
+ }).then(() => current2);
95501
96368
  verificationConsumeLocks.set(key, next);
95502
96369
  await previous.catch(() => {
95503
96370
  });
@@ -105371,9 +106238,9 @@ function createAtomicFallbacks(context2) {
105371
106238
  for (const [field, delta] of deltas) {
105372
106239
  const previous = counterSchema.safeParse(row[field]);
105373
106240
  if (!previous.success) throw new BetterAuthError(`Adapter "${adapterId}" must return finite numeric counter values or null for atomic increments.`);
105374
- const current = previous.data ?? 0;
105375
- const next = current + delta;
105376
- if (!Number.isFinite(next) || delta !== 0 && next === current) throw new BetterAuthError(`Adapter "${adapterId}" cannot represent the requested counter increment safely.`);
106241
+ const current2 = previous.data ?? 0;
106242
+ const next = current2 + delta;
106243
+ if (!Number.isFinite(next) || delta !== 0 && next === current2) throw new BetterAuthError(`Adapter "${adapterId}" cannot represent the requested counter increment safely.`);
105377
106244
  update[field] = next;
105378
106245
  }
105379
106246
  const guard = await snapshotGuard(row, fields, request, "incrementOne");
@@ -127719,9 +128586,9 @@ function validateSecretsArray(secrets, logger3) {
127719
128586
  if (seen.has(version4)) throw new BetterAuthError(`Duplicate version ${version4} in \`secrets\`. Each version must be unique.`);
127720
128587
  seen.add(version4);
127721
128588
  }
127722
- const current = secrets[0];
127723
- if (current.value.length < 32) logger3.warn(`[better-auth] Warning: the current secret (version ${current.version}) should be at least 32 characters long for adequate security.`);
127724
- if (estimateEntropy(current.value) < 120) logger3.warn("[better-auth] Warning: the current secret appears low-entropy. Use a randomly generated secret for production.");
128589
+ const current2 = secrets[0];
128590
+ if (current2.value.length < 32) logger3.warn(`[better-auth] Warning: the current secret (version ${current2.version}) should be at least 32 characters long for adequate security.`);
128591
+ if (estimateEntropy(current2.value) < 120) logger3.warn("[better-auth] Warning: the current secret appears low-entropy. Use a randomly generated secret for production.");
127725
128592
  }
127726
128593
  function buildSecretConfig(secrets, legacySecret) {
127727
128594
  const keys = /* @__PURE__ */ new Map();
@@ -137676,7 +138543,7 @@ var init_connector_authentication_setup = __esm({
137676
138543
  });
137677
138544
 
137678
138545
  // ../shared/src/connector-schemas.ts
137679
- var CONNECTOR_OPERATION_SELECTION_LIMIT, CONNECTOR_AUTHENTICATION_FLOW_TTL_MS, CONNECTOR_EVENT_REVIEW_SCOPE_LIMIT, ConnectorJsonValueSchema, ConnectorJsonObjectSchema, ConnectorProviderInstanceIdSchema, ConnectionIdSchema, ConnectorExternalAccountRefSchema, ConnectorProviderModeSchema, ConnectorProviderHealthSchema, ConnectorGrantReconciliationStatusSchema, ConnectorOperationClassificationSchema, ConnectorRetryPolicySchema, ConnectorOperationRevisionSchema, ConnectorOperationPageSchema, ConnectorCapabilityAvailabilitySchema, ConnectorUnsupportedResultSchema, ConnectorProviderCapabilitySetSchema, ConnectorToolkitVersionResultSchema, ConnectorProviderExecuteResultSchema, ConnectorAuthenticationFlowSchema, ConnectorExecutionTargetSchema, ConnectorProgramExecutionRequestSchema, ConnectorExecutionPublicResultSchema, ConnectorExecutionResponseSchema, ConnectionReadinessStateSchema, ConnectionReadinessReasonSchema, ConnectionFixActionSchema, ConnectionFixSchema, ConnectionReadinessSchema, READINESS_ASK_ON_CONNECTIONS, CONNECTION_GONE_AGENT_COPY, CONNECTION_READINESS_COPY, AccessibleConnectorConnectionSchema, AccessibleConnectorOperationSchema, ConnectorAccessibleConnectionsResponseSchema, ConnectorAccessibleOperationsResponseSchema, ConnectorUsageItemSchema, ConnectorUsagePageSchema, ConnectorReconciliationPreviewRequestSchema, ConnectorReconciliationGrantSelectionSchema, ConnectorReconciliationEveryAgentSelectionSchema, ConnectorReconciliationEveryAgentStateSchema, ConnectorEveryAgentRevokeResponseSchema, ConnectorReconciliationAgentSchema, ConnectorReconciliationCandidateSchema, ConnectorReconciliationPreviewSchema, ConnectorReconciliationApplyRequestSchema, ConnectorReconciliationApplyResponseSchema, ReviewActionBaseSchema, ConnectionTargetSchema, ConnectorRequestAccessSchema, ConnectorReviewActionSchema, ConnectorAgentConnectionRequestInputSchema, ConnectorAgentRequestBaseSchema, ConnectorRequestNotGrantedSchema, ConnectorAgentRequestStatusSchema, ConnectorAgentRequestItemSchema, ConnectorAgentRequestListResponseSchema, ConnectorManagementConnectActionSchema, ConnectorManagementAppliedActionSchema, ConnectorManagementReviewActionSchema, ConnectorManagementReviewCreateRequestSchema, ConnectorManagementReviewOutcomeSchema, ConnectorManagementReviewOperationContextSchema, ConnectorManagementReviewConnectionContextSchema, ConnectorManagementReviewAgentContextSchema, ConnectorManagementReviewContextSchema, ManagementReviewItemBaseShape, ConnectorPendingManagementReviewItemSchema, ConnectorResolvingManagementReviewItemSchema, ConnectorExpiredManagementReviewItemSchema, ConnectorDeniedManagementReviewItemSchema, ConnectorApprovedAppliedManagementReviewItemSchema, ConnectorApprovedConnectManagementReviewItemSchema, ConnectorApprovedUnknownManagementReviewItemSchema, ConnectorManagementReviewItemSchema, ProgramReviewStatusBaseShape, ConnectorProgramReviewStatusSchema, ConnectorManagementReviewDecisionSchema, ConnectorManagementReviewDecisionResultSchema;
138546
+ var CONNECTOR_OPERATION_SELECTION_LIMIT, CONNECTOR_AUTHENTICATION_FLOW_TTL_MS, CONNECTOR_EVENT_REVIEW_SCOPE_LIMIT, ConnectorJsonValueSchema, ConnectorJsonObjectSchema, ConnectorProviderInstanceIdSchema, ConnectionIdSchema, ConnectorExternalAccountRefSchema, ConnectorProviderModeSchema, ConnectorProviderHealthSchema, ConnectorGrantReconciliationStatusSchema, ConnectorOperationClassificationSchema, ConnectorAccessLevelSchema, ConnectorRetryPolicySchema, ConnectorOperationRevisionSchema, ConnectorOperationPageSchema, ConnectorCapabilityAvailabilitySchema, ConnectorUnsupportedResultSchema, ConnectorProviderCapabilitySetSchema, ConnectorToolkitVersionResultSchema, ConnectorProviderExecuteResultSchema, ConnectorAuthenticationFlowSchema, ConnectorExecutionTargetSchema, ConnectorProgramExecutionRequestSchema, ConnectorExecutionPublicResultSchema, ConnectorExecutionResponseSchema, ConnectionReadinessStateSchema, ConnectionReadinessReasonSchema, ConnectionFixActionSchema, ConnectionFixSchema, ConnectionReadinessSchema, READINESS_ASK_ON_CONNECTIONS, CONNECTION_GONE_AGENT_COPY, CONNECTION_READINESS_COPY, AccessibleConnectorConnectionSchema, AccessibleConnectorOperationSchema, ConnectorAccessibleConnectionsResponseSchema, ConnectorAccessibleOperationsResponseSchema, ConnectorUsageItemSchema, ConnectorUsagePageSchema, ConnectorReconciliationPreviewRequestSchema, ConnectorReconciliationGrantSelectionSchema, ConnectorReconciliationEveryAgentSelectionSchema, ConnectorReconciliationEveryAgentStateSchema, ConnectorEveryAgentRevokeResponseSchema, ConnectorReconciliationAgentSchema, ConnectorReconciliationCandidateSchema, ConnectorReconciliationPreviewSchema, ConnectorReconciliationApplyRequestSchema, ConnectorReconciliationApplyResponseSchema, ReviewActionBaseSchema, ConnectionTargetSchema, ConnectorRequestAccessSchema, ConnectorReviewActionSchema, ConnectorAgentConnectionRequestInputSchema, ConnectorAgentRequestBaseSchema, ConnectorRequestNotGrantedSchema, ConnectorAgentRequestStatusSchema, ConnectorAgentRequestItemSchema, ConnectorAgentRequestListResponseSchema, ConnectorManagementConnectActionSchema, ConnectorManagementAppliedActionSchema, ConnectorManagementReviewActionSchema, ConnectorManagementReviewCreateRequestSchema, ConnectorManagementReviewOutcomeSchema, ConnectorManagementReviewOperationContextSchema, ConnectorManagementReviewConnectionContextSchema, ConnectorManagementReviewAgentContextSchema, ConnectorManagementReviewContextSchema, ManagementReviewItemBaseShape, ConnectorPendingManagementReviewItemSchema, ConnectorResolvingManagementReviewItemSchema, ConnectorExpiredManagementReviewItemSchema, ConnectorDeniedManagementReviewItemSchema, ConnectorApprovedAppliedManagementReviewItemSchema, ConnectorApprovedConnectManagementReviewItemSchema, ConnectorApprovedUnknownManagementReviewItemSchema, ConnectorManagementReviewItemSchema, ProgramReviewStatusBaseShape, ConnectorProgramReviewStatusSchema, ConnectorManagementReviewDecisionSchema, ConnectorManagementReviewDecisionResultSchema;
137680
138547
  var init_connector_schemas = __esm({
137681
138548
  "../shared/src/connector-schemas.ts"() {
137682
138549
  init_zod();
@@ -137717,6 +138584,7 @@ var init_connector_schemas = __esm({
137717
138584
  "migration_needs_reconcile"
137718
138585
  ]);
137719
138586
  ConnectorOperationClassificationSchema = external_exports.enum(["read", "write", "destructive"]);
138587
+ ConnectorAccessLevelSchema = external_exports.enum(["read", "read-write"]);
137720
138588
  ConnectorRetryPolicySchema = external_exports.enum(["never", "provider_idempotency_key"]);
137721
138589
  ConnectorOperationRevisionSchema = external_exports.object({
137722
138590
  id: external_exports.string().min(1),
@@ -138063,14 +138931,19 @@ var init_connector_schemas = __esm({
138063
138931
  ConnectorReconciliationPreviewRequestSchema = external_exports.object({ connectionId: ConnectionIdSchema }).strict();
138064
138932
  ConnectorReconciliationGrantSelectionSchema = external_exports.object({
138065
138933
  agentId: external_exports.string().min(1),
138066
- operationRevisionIds: external_exports.array(external_exports.string().min(1))
138934
+ operationRevisionIds: external_exports.array(external_exports.string().min(1)),
138935
+ level: ConnectorAccessLevelSchema.optional()
138067
138936
  }).strict();
138068
138937
  ConnectorReconciliationEveryAgentSelectionSchema = external_exports.object({
138069
- operationRevisionIds: external_exports.array(external_exports.string().min(1))
138938
+ operationRevisionIds: external_exports.array(external_exports.string().min(1)),
138939
+ /** The level these revisions are, kept as the app changes; absent for exact actions. */
138940
+ level: ConnectorAccessLevelSchema.optional()
138070
138941
  }).strict();
138071
138942
  ConnectorReconciliationEveryAgentStateSchema = external_exports.object({
138072
138943
  available: external_exports.boolean(),
138073
- operationRevisionIds: external_exports.array(external_exports.string().min(1))
138944
+ operationRevisionIds: external_exports.array(external_exports.string().min(1)),
138945
+ /** The level the owner chose for every agent; absent for exact actions or no sharing. */
138946
+ level: ConnectorAccessLevelSchema.optional()
138074
138947
  }).strict();
138075
138948
  ConnectorEveryAgentRevokeResponseSchema = external_exports.object({
138076
138949
  connectionId: ConnectionIdSchema,
@@ -138116,7 +138989,7 @@ var init_connector_schemas = __esm({
138116
138989
  ConnectionTargetSchema = ReviewActionBaseSchema.extend({
138117
138990
  connectionId: ConnectionIdSchema
138118
138991
  }).strict();
138119
- ConnectorRequestAccessSchema = external_exports.enum(["read", "read-write"]);
138992
+ ConnectorRequestAccessSchema = ConnectorAccessLevelSchema;
138120
138993
  ConnectorReviewActionSchema = external_exports.discriminatedUnion("kind", [
138121
138994
  ReviewActionBaseSchema.extend({
138122
138995
  kind: external_exports.literal("connect"),
@@ -138596,7 +139469,14 @@ var init_connector_provider = __esm({
138596
139469
  /** Why a configured provider is not registered (secret-free), when it isn't. */
138597
139470
  error: external_exports.string().optional(),
138598
139471
  /** Which credential kind the stored key validated as, when the provider reports it. */
138599
- keyKind: ConnectorKeyKindSchema.optional()
139472
+ keyKind: ConnectorKeyKindSchema.optional(),
139473
+ /**
139474
+ * When DorkOS checks this key again on its own, while a check is scheduled
139475
+ * or running (a running one reads as now). Absent once it has stopped
139476
+ * trying, so a client showing the error knows to read the status again
139477
+ * and pick up the new line.
139478
+ */
139479
+ recheckAt: external_exports.string().datetime().optional()
138600
139480
  });
138601
139481
  ConnectorRecommendationKindSchema = external_exports.enum(["relay-adapter", "gateway", "raw-mcp"]);
138602
139482
  ConnectorRecommendationSchema = external_exports.object({
@@ -143779,12 +144659,12 @@ function flattenConfig(obj, prefix = "") {
143779
144659
  }
143780
144660
  function getDefault(key) {
143781
144661
  const parts = key.split(".");
143782
- let current = USER_CONFIG_DEFAULTS;
144662
+ let current2 = USER_CONFIG_DEFAULTS;
143783
144663
  for (const part of parts) {
143784
- if (current === null || typeof current !== "object") return void 0;
143785
- current = current[part];
144664
+ if (current2 === null || typeof current2 !== "object") return void 0;
144665
+ current2 = current2[part];
143786
144666
  }
143787
- return current;
144667
+ return current2;
143788
144668
  }
143789
144669
  function handleConfigDefault(store) {
143790
144670
  const config3 = store.getAll();
@@ -143816,20 +144696,20 @@ function formatConfigValue(value) {
143816
144696
  }
143817
144697
  function splitDotPath(key) {
143818
144698
  const segments = [];
143819
- let current = "";
144699
+ let current2 = "";
143820
144700
  for (let index2 = 0; index2 < key.length; index2 += 1) {
143821
144701
  const char = key[index2];
143822
144702
  if (char === "\\" && index2 + 1 < key.length) {
143823
- current += key[index2 + 1];
144703
+ current2 += key[index2 + 1];
143824
144704
  index2 += 1;
143825
144705
  } else if (char === ".") {
143826
- segments.push(current);
143827
- current = "";
144706
+ segments.push(current2);
144707
+ current2 = "";
143828
144708
  } else {
143829
- current += char;
144709
+ current2 += char;
143830
144710
  }
143831
144711
  }
143832
- segments.push(current);
144712
+ segments.push(current2);
143833
144713
  return segments;
143834
144714
  }
143835
144715
  function patchForPath(key, value) {
@@ -144652,7 +145532,7 @@ if (process.argv[2] === "community") {
144652
145532
  })
144653
145533
  );
144654
145534
  const exitCode = await dispatcher.runCommunityDispatcher(process.argv.slice(3), {
144655
- cliVersion: "0.92.0",
145535
+ cliVersion: "0.93.0",
144656
145536
  dorkHome: DORK_HOME,
144657
145537
  processEnv: childEnv,
144658
145538
  parseRelease: (bytes) => releaseContract.parseCompatibleCommunityReleaseManifest(
@@ -144660,7 +145540,7 @@ if (process.argv[2] === "community") {
144660
145540
  {
144661
145541
  platform: { os: "linux", architecture: "amd64" },
144662
145542
  configSchemaVersion: releaseContract.COMMUNITY_CONFIG_SCHEMA_VERSION,
144663
- migrationCompatibilityId: "sha256:fda264096ca0d6d4da2413c62527af3a89266af2a101954a429aff2ee3212e37"
145543
+ migrationCompatibilityId: "sha256:a97601bea5580e9a1502e3cb0f9aabe991e7db5809b159cdd3a669649c2d55bd"
144664
145544
  }
144665
145545
  )
144666
145546
  });
@@ -144670,7 +145550,7 @@ if (process.argv[2] === "community") {
144670
145550
  process.exit(1);
144671
145551
  }
144672
145552
  }
144673
- var cliErrorReporter = initCliErrorReporting({ dorkHome: DORK_HOME, version: "0.92.0" });
145553
+ var cliErrorReporter = initCliErrorReporting({ dorkHome: DORK_HOME, version: "0.93.0" });
144674
145554
  var uninstallCliErrorHandlers = cliErrorReporter ? installCliErrorHandlers(cliErrorReporter) : void 0;
144675
145555
  if (process.argv[2] === "doctor") {
144676
145556
  process.env.DORK_HOME = DORK_HOME;
@@ -144680,7 +145560,7 @@ if (process.argv[2] === "doctor") {
144680
145560
  if (process.argv[2] === "feedback") {
144681
145561
  process.env.DORK_HOME = DORK_HOME;
144682
145562
  const { runFeedback: runFeedback2 } = await Promise.resolve().then(() => (init_feedback2(), feedback_exports));
144683
- process.exit(await runFeedback2(DORK_HOME, "0.92.0", process.argv.slice(3)));
145563
+ process.exit(await runFeedback2(DORK_HOME, "0.93.0", process.argv.slice(3)));
144684
145564
  }
144685
145565
  if (process.argv[2] === "auth") {
144686
145566
  process.env.DORK_HOME = DORK_HOME;
@@ -144779,7 +145659,7 @@ if (process.argv[2] === "agent" || process.argv[2] === "task" || process.argv[2]
144779
145659
  }
144780
145660
  }
144781
145661
  const { runVersionDispatcher: runVersionDispatcher2 } = await Promise.resolve().then(() => (init_version5(), version_exports));
144782
- process.exit(await runVersionDispatcher2("0.92.0", DORK_HOME, subArgs));
145662
+ process.exit(await runVersionDispatcher2("0.93.0", DORK_HOME, subArgs));
144783
145663
  }
144784
145664
  function parseCliArgs() {
144785
145665
  try {
@@ -144904,14 +145784,14 @@ Examples:
144904
145784
  process.exit(0);
144905
145785
  }
144906
145786
  if (values.version) {
144907
- console.log("0.92.0");
145787
+ console.log("0.93.0");
144908
145788
  process.exit(0);
144909
145789
  }
144910
145790
  if (values["post-install-check"]) {
144911
145791
  const claudeFound = checkClaude();
144912
145792
  const coreExtensionsFound = checkCoreExtensions();
144913
145793
  const extensionsCompile = await checkExtensionCompilation();
144914
- console.log(`dorkos ${"0.92.0"}`);
145794
+ console.log(`dorkos ${"0.93.0"}`);
144915
145795
  if (!coreExtensionsFound) {
144916
145796
  console.log("Installation incomplete \u2014 bundled core extensions are missing.");
144917
145797
  }
@@ -145065,7 +145945,7 @@ if (fs31.existsSync(envPath)) {
145065
145945
  }
145066
145946
  uninstallCliErrorHandlers?.();
145067
145947
  process.env.DORKOS_CLI_ENTRYPOINT = fileURLToPath6(import.meta.url);
145068
- process.env.DORKOS_CLI_VERSION = "0.92.0";
145948
+ process.env.DORKOS_CLI_VERSION = "0.93.0";
145069
145949
  var server;
145070
145950
  try {
145071
145951
  server = await import("../server/index.js");
@@ -145090,7 +145970,7 @@ var ansiReset = "\x1B[0m";
145090
145970
  console.log("");
145091
145971
  console.log(`${purple}${logo}${ansiReset}`);
145092
145972
  console.log("");
145093
- console.log(` DorkOS v${"0.92.0"}`);
145973
+ console.log(` DorkOS v${"0.93.0"}`);
145094
145974
  console.log(` Local: ${link(localUrl, localUrl)}`);
145095
145975
  var nets = networkInterfaces();
145096
145976
  var networkUrl = null;
@@ -145116,9 +145996,9 @@ if (shouldOpenBrowser && process.stdin.isTTY) {
145116
145996
  const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
145117
145997
  exec(`${openCmd} ${localUrl}`);
145118
145998
  }
145119
- checkForUpdate("0.92.0").then((latestVersion) => {
145999
+ checkForUpdate("0.93.0").then((latestVersion) => {
145120
146000
  if (latestVersion) {
145121
- const msg = `Update available: ${"0.92.0"} \u2192 ${latestVersion}`;
146001
+ const msg = `Update available: ${"0.93.0"} \u2192 ${latestVersion}`;
145122
146002
  const cmd = "Run npm install -g dorkos@latest to update";
145123
146003
  const width = Math.max(msg.length, cmd.length) + 6;
145124
146004
  const pad2 = (s2) => `\u2502 ${s2}${" ".repeat(width - s2.length - 6)} \u2502`;