sh3-core 0.22.0 → 0.22.2

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 (80) hide show
  1. package/dist/__test__/fixtures.js +1 -1
  2. package/dist/__test__/reset.js +1 -3
  3. package/dist/__test__/smoke.test.js +2 -2
  4. package/dist/actions/contextMenuModel.test.js +6 -3
  5. package/dist/actions/ctx-actions.svelte.test.js +9 -9
  6. package/dist/actions/dispatcher-v3.test.js +8 -0
  7. package/dist/actions/dispatcher.svelte.d.ts +1 -2
  8. package/dist/actions/dispatcher.svelte.js +6 -7
  9. package/dist/actions/dispatcher.test.js +9 -12
  10. package/dist/actions/listActionsFromEntries.test.js +1 -2
  11. package/dist/actions/listActive.test.js +2 -3
  12. package/dist/actions/menuBarModel.test.js +1 -7
  13. package/dist/actions/paletteModel.test.js +1 -3
  14. package/dist/actions/scope-helpers.test.js +4 -4
  15. package/dist/actions/shardContext.test.js +2 -2
  16. package/dist/actions/state.svelte.d.ts +12 -2
  17. package/dist/actions/state.svelte.js +15 -12
  18. package/dist/actions/state.test.js +4 -4
  19. package/dist/api.d.ts +4 -3
  20. package/dist/api.js +1 -1
  21. package/dist/app/admin/adminShard.svelte.js +1 -1
  22. package/dist/app/store/storeShard.svelte.js +10 -5
  23. package/dist/app-appearance/appearanceShard.svelte.js +1 -5
  24. package/dist/apps/lifecycle.js +49 -64
  25. package/dist/apps/lifecycle.test.js +30 -76
  26. package/dist/conflicts/adapter-documents.js +1 -2
  27. package/dist/createShell.js +1 -1
  28. package/dist/documents/handle.d.ts +9 -4
  29. package/dist/documents/handle.js +40 -29
  30. package/dist/documents/handle.test.js +60 -51
  31. package/dist/documents/index.d.ts +1 -1
  32. package/dist/documents/types.d.ts +16 -26
  33. package/dist/host.d.ts +1 -1
  34. package/dist/host.js +9 -56
  35. package/dist/host.svelte.test.js +31 -63
  36. package/dist/layouts-shard/LayoutsSection.svelte +1 -1
  37. package/dist/layouts-shard/layoutsShard.svelte.js +2 -5
  38. package/dist/layouts-shard/layoutsShard.svelte.test.js +2 -2
  39. package/dist/projects-shard/projectsShard.svelte.js +1 -5
  40. package/dist/registry/installer.js +1 -1
  41. package/dist/registry/loader.d.ts +1 -1
  42. package/dist/registry/loader.js +3 -3
  43. package/dist/registry/permission-descriptions.test.js +2 -2
  44. package/dist/registry/register.js +1 -1
  45. package/dist/registry/register.test.js +1 -1
  46. package/dist/runtime/runVerb-shell.test.js +1 -1
  47. package/dist/runtime/runVerb.js +2 -2
  48. package/dist/runtime/runVerb.test.js +9 -9
  49. package/dist/server-shard/types.d.ts +56 -0
  50. package/dist/sh3Api/headless.js +1 -1
  51. package/dist/sh3core-shard/sh3coreShard.svelte.js +1 -6
  52. package/dist/shards/ctx-fetch.test.js +9 -9
  53. package/dist/shards/lifecycle.svelte.d.ts +108 -0
  54. package/dist/shards/lifecycle.svelte.js +551 -0
  55. package/dist/shards/lifecycle.test.js +139 -0
  56. package/dist/shards/types.d.ts +30 -63
  57. package/dist/shell-shard/shellShard.svelte.js +1 -4
  58. package/dist/version.d.ts +1 -1
  59. package/dist/version.js +1 -1
  60. package/package.json +1 -1
  61. package/dist/shards/activate-browse.test.js +0 -120
  62. package/dist/shards/activate-contributions.test.js +0 -141
  63. package/dist/shards/activate-error-isolation.test.d.ts +0 -1
  64. package/dist/shards/activate-error-isolation.test.js +0 -98
  65. package/dist/shards/activate-fields.svelte.test.d.ts +0 -1
  66. package/dist/shards/activate-fields.svelte.test.js +0 -121
  67. package/dist/shards/activate-on-key-revoked.test.d.ts +0 -1
  68. package/dist/shards/activate-on-key-revoked.test.js +0 -60
  69. package/dist/shards/activate-runtime.test.d.ts +0 -1
  70. package/dist/shards/activate-runtime.test.js +0 -344
  71. package/dist/shards/activate-scopeid.test.d.ts +0 -1
  72. package/dist/shards/activate-scopeid.test.js +0 -21
  73. package/dist/shards/activate.svelte.d.ts +0 -102
  74. package/dist/shards/activate.svelte.js +0 -407
  75. package/dist/shards/app-binding.svelte.d.ts +0 -8
  76. package/dist/shards/app-binding.svelte.js +0 -30
  77. package/dist/shards/app-binding.test.d.ts +0 -1
  78. package/dist/shards/app-binding.test.js +0 -25
  79. /package/dist/{shards/activate-browse.test.d.ts → actions/dispatcher-v3.test.d.ts} +0 -0
  80. /package/dist/shards/{activate-contributions.test.d.ts → lifecycle.test.d.ts} +0 -0
@@ -40,7 +40,7 @@ describe('describePermission — documents:read / documents:write', () => {
40
40
  function shardWithPerms(id, perms) {
41
41
  return {
42
42
  manifest: { id, label: id, version: '0.0.0', views: [], permissions: perms },
43
- activate: () => { },
43
+ register: () => { },
44
44
  };
45
45
  }
46
46
  function appWithPerms(id, perms) {
@@ -54,7 +54,7 @@ function appWithPerms(id, perms) {
54
54
  layoutVersion: 1,
55
55
  permissions: perms,
56
56
  },
57
- activate: () => { },
57
+ register: () => { },
58
58
  };
59
59
  }
60
60
  describe('extractBundlePermissions', () => {
@@ -8,7 +8,7 @@
8
8
  * manifests; the authoritative value comes from the persisted/server
9
9
  * metadata and must be stamped here before any consumer reads the manifest.
10
10
  */
11
- import { registerShard } from '../shards/activate.svelte';
11
+ import { registerShard } from '../shards/lifecycle.svelte';
12
12
  import { registerApp } from '../apps/registry.svelte';
13
13
  export function registerLoadedBundle(loaded, meta) {
14
14
  for (const shard of loaded.shards) {
@@ -3,7 +3,7 @@ import { resetFramework } from '../__test__/reset';
3
3
  import { makeApp, makeAppManifest, makeShard, makeShardManifest } from '../__test__/fixtures';
4
4
  import { registerLoadedBundle } from './register';
5
5
  import { registeredApps } from '../apps/registry.svelte';
6
- import { registeredShards } from '../shards/activate.svelte';
6
+ import { registeredShards } from '../shards/lifecycle.svelte';
7
7
  describe('registerLoadedBundle', () => {
8
8
  beforeEach(resetFramework);
9
9
  it('stamps meta.version onto every shard manifest before registering', () => {
@@ -12,7 +12,7 @@
12
12
  import { describe, it, expect, beforeEach } from 'vitest';
13
13
  import { MemoryDocumentBackend } from '../documents/backends';
14
14
  import { __setDocumentBackend, __setActiveScope } from '../documents/config';
15
- import { registerShard, activateShard, __resetShardRegistryForTest, } from '../shards/activate.svelte';
15
+ import { registerShard, activateShard, __resetShardRegistryForTest, } from '../shards/lifecycle.svelte';
16
16
  import { __resetViewRegistryForTest } from '../shards/registry';
17
17
  import { __resetActionsRegistryForTest } from '../actions/registry';
18
18
  import { runVerbProgrammatic } from './runVerb';
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * runVerbProgrammatic — programmatic verb dispatch with synthesized VerbContext.
3
3
  *
4
- * Used by `ctx.runVerb(...)` (see shards/activate.svelte.ts). Builds a
4
+ * Used by `ctx.runVerb(...)` (see shards/lifecycle.svelte.ts). Builds a
5
5
  * sink scrollback that captures entries into an array, a headless Sh3Api
6
6
  * (no terminal-bound state), a stub SessionClient, and a real TenantFsClient.
7
7
  * Verbs that opt in via `programmatic: true` run against this synthesized
@@ -15,7 +15,7 @@
15
15
  * Resolution: prefixed names (`'sh3-store:install'`) look up directly;
16
16
  * unprefixed sh3 names (`'apps'`) resolve against shardId 'sh3'.
17
17
  */
18
- import { activeShards } from '../shards/activate.svelte';
18
+ import { activeShards } from '../shards/lifecycle.svelte';
19
19
  import { getVerb, listVerbsWithShard } from '../shards/registry';
20
20
  import { makeSh3Api } from '../sh3Api/headless';
21
21
  import { Scrollback } from '../shell-shard/scrollback.svelte';
@@ -1,7 +1,7 @@
1
1
  import { describe, it, expect, beforeEach } from 'vitest';
2
2
  import { MemoryDocumentBackend } from '../documents/backends';
3
3
  import { __setDocumentBackend, __setActiveScope } from '../documents/config';
4
- import { registerShard, activateShard, __resetShardRegistryForTest, } from '../shards/activate.svelte';
4
+ import { registerShard, activateShard, __resetShardRegistryForTest, } from '../shards/lifecycle.svelte';
5
5
  import { __resetViewRegistryForTest } from '../shards/registry';
6
6
  import { runVerbProgrammatic } from './runVerb';
7
7
  function makeVerb(name, programmatic, body = async () => undefined) {
@@ -27,7 +27,7 @@ describe('runVerbProgrammatic', () => {
27
27
  it('rejects on unknown verb', async () => {
28
28
  registerShard({
29
29
  manifest: { id: 'tester', label: 'T', version: '0.0.0', views: [] },
30
- activate(ctx) {
30
+ register(ctx) {
31
31
  ctx.registerVerb(makeVerb('echo', true));
32
32
  },
33
33
  });
@@ -37,7 +37,7 @@ describe('runVerbProgrammatic', () => {
37
37
  it('rejects when verb is not programmatic', async () => {
38
38
  registerShard({
39
39
  manifest: { id: 'tester', label: 'T', version: '0.0.0', views: [] },
40
- activate(ctx) {
40
+ register(ctx) {
41
41
  ctx.registerVerb(makeVerb('plain', false));
42
42
  },
43
43
  });
@@ -47,7 +47,7 @@ describe('runVerbProgrammatic', () => {
47
47
  it('invokes a programmatic verb and resolves with { result, scrollback }', async () => {
48
48
  registerShard({
49
49
  manifest: { id: 'tester', label: 'T', version: '0.0.0', views: [] },
50
- activate(ctx) {
50
+ register(ctx) {
51
51
  ctx.registerVerb(makeVerb('echo', true, async (vctx, args) => {
52
52
  vctx.scrollback.push({
53
53
  kind: 'status',
@@ -71,7 +71,7 @@ describe('runVerbProgrammatic', () => {
71
71
  let observed = undefined;
72
72
  registerShard({
73
73
  manifest: { id: 'tester', label: 'T', version: '0.0.0', views: [] },
74
- activate(ctx) {
74
+ register(ctx) {
75
75
  ctx.registerVerb(makeVerb('capture', true, async (vctx) => {
76
76
  observed = vctx.structuredArgs;
77
77
  }));
@@ -85,7 +85,7 @@ describe('runVerbProgrammatic', () => {
85
85
  let received;
86
86
  registerShard({
87
87
  manifest: { id: 'tester', label: 'T', version: '0.0.0', views: [] },
88
- activate(ctx) {
88
+ register(ctx) {
89
89
  ctx.registerVerb(makeVerb('peek', true, async (vctx) => {
90
90
  received = vctx.signal;
91
91
  }));
@@ -99,7 +99,7 @@ describe('runVerbProgrammatic', () => {
99
99
  it('inner dispatch re-enters runVerb and merges scrollback into the outer capture', async () => {
100
100
  registerShard({
101
101
  manifest: { id: 'tester', label: 'T', version: '0.0.0', views: [] },
102
- activate(ctx) {
102
+ register(ctx) {
103
103
  ctx.registerVerb(makeVerb('inner', true, async (vctx) => {
104
104
  vctx.scrollback.push({ kind: 'status', text: 'inner-fired', level: 'info', ts: 0 });
105
105
  }));
@@ -120,7 +120,7 @@ describe('runVerbProgrammatic', () => {
120
120
  it('propagates an error thrown by the verb', async () => {
121
121
  registerShard({
122
122
  manifest: { id: 'tester', label: 'T', version: '0.0.0', views: [] },
123
- activate(ctx) {
123
+ register(ctx) {
124
124
  ctx.registerVerb(makeVerb('boom', true, async () => {
125
125
  throw new Error('kaboom');
126
126
  }));
@@ -133,7 +133,7 @@ describe('runVerbProgrammatic', () => {
133
133
  let observed = undefined;
134
134
  registerShard({
135
135
  manifest: { id: 'tester', label: 'T', version: '0.0.0', views: [] },
136
- activate(ctx) {
136
+ register(ctx) {
137
137
  ctx.registerVerb(makeVerb('peek-sh3', true, async (vctx) => {
138
138
  observed = vctx.sh3.dispatchToTerminal('foo');
139
139
  }));
@@ -12,6 +12,19 @@
12
12
  */
13
13
  import type { DocumentMeta } from '../documents/types';
14
14
  import type { SyncPolicy, ConflictFile } from '../documents/sync-types';
15
+ /** Public shape of an API key — never includes the secret value. */
16
+ export interface ApiKeyPublic {
17
+ id: string;
18
+ label: string;
19
+ scopeId: string | null;
20
+ ownerUserId: string | null;
21
+ mintedByShardId: string | null;
22
+ scopes: string[];
23
+ peerRole?: 'primary' | 'replica';
24
+ peerId?: string;
25
+ createdAt: string;
26
+ expiresAt?: string;
27
+ }
15
28
  /**
16
29
  * Per-tenant document API exposed to server shards via
17
30
  * `ServerShardContext.documents(tenantId)`. Every method is
@@ -95,6 +108,49 @@ export interface ServerShardContext {
95
108
  * Absent => 'primary' behavior at the store.
96
109
  */
97
110
  setPeerRole(tenant: string, role: 'primary' | 'replica'): void;
111
+ /**
112
+ * Redeem a consent ticket and return the freshly-minted key.
113
+ *
114
+ * The browser side of your shard calls `POST /api/keys/consent` to issue
115
+ * a ticket bound to the user's session. The server side hands the
116
+ * ticket to this method to mint the key. The ticket carries the
117
+ * `(scopeId, userId, shardId, label, scopes, expiresIn?)` from consent
118
+ * — none of those are caller-controlled here, so a shard cannot escalate
119
+ * its own scopes or mint for a different tenant.
120
+ *
121
+ * The caller's `scopeId` is read from the Hono request context (`c`) and
122
+ * must match the scope recorded on the ticket; mismatches return `null`
123
+ * (same as expired / unknown ticket — probe-resistant).
124
+ *
125
+ * The returned `key` is the full secret string. Return it to the user
126
+ * exactly once and never persist it server-side; subsequent calls only
127
+ * see `key.id` via `listKeys`.
128
+ *
129
+ * @param c The Hono request context for the route handler.
130
+ * @param ticket The opaque token issued by /api/keys/consent.
131
+ * @returns `{ id, key }` on success, `null` on invalid / expired / scope-mismatch.
132
+ */
133
+ redeemKeyTicket(c: unknown, ticket: string): Promise<{
134
+ id: string;
135
+ key: string;
136
+ } | null>;
137
+ /**
138
+ * List API keys this shard has minted for the calling caller's scope.
139
+ * Filtered to `mintedByShardId === ctx.shardId`. Other shards' keys are
140
+ * invisible. Returns an empty array if the caller has no scope.
141
+ */
142
+ listKeys(c: unknown): Promise<ApiKeyPublic[]>;
143
+ /**
144
+ * Revoke an API key by id. Only revokes keys minted by this shard
145
+ * (`mintedByShardId === ctx.shardId`) for the calling caller's scope.
146
+ * Attempting to revoke another shard's key or a key in a different
147
+ * tenant returns `false` without raising.
148
+ *
149
+ * Successful revocations fire `onKeyRevoked` on the client side via
150
+ * the existing SSE channel — same path the browser-driven DELETE
151
+ * already takes.
152
+ */
153
+ revokeKey(c: unknown, id: string): Promise<boolean>;
98
154
  /**
99
155
  * Translate an SH3 document path to a real filesystem path on the host.
100
156
  *
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { listRegisteredApps, getActiveApp } from '../apps/registry.svelte';
17
17
  import { launchApp } from '../apps/lifecycle';
18
- import { registeredShards, listStandaloneViews } from '../shards/activate.svelte';
18
+ import { registeredShards, listStandaloneViews } from '../shards/lifecycle.svelte';
19
19
  import { inspectActiveLayout, focusView, closeTab, popoutView, dockFloat, dockIntoActiveLayout, locateSlot as locateSlotInActiveLayout, } from '../layout/inspection';
20
20
  import { floatManager } from '../overlays/float';
21
21
  import { getUser, isAdmin } from '../auth/index';
@@ -65,7 +65,7 @@ export const sh3coreShard = {
65
65
  { id: 'sh3:keys-and-peers', label: 'Keys & Peers' },
66
66
  ],
67
67
  },
68
- activate(ctx) {
68
+ register(ctx) {
69
69
  const zones = ctx.state({
70
70
  user: {
71
71
  bindings: {},
@@ -165,9 +165,4 @@ export const sh3coreShard = {
165
165
  });
166
166
  });
167
167
  },
168
- autostart() {
169
- // Intentionally empty. Defining this field is what puts the sh3core
170
- // pseudo-shard on the self-starting path at boot (see bootstrap),
171
- // so `sh3core:home` is available before any app launches.
172
- },
173
168
  };
@@ -2,7 +2,7 @@ import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
2
2
  import { MemoryDocumentBackend } from '../documents/backends';
3
3
  import { __setDocumentBackend, __setActiveScope } from '../documents/config';
4
4
  import { __setEnvServerUrl } from '../env/index';
5
- import { registerShard, activateShard, __resetShardRegistryForTest, } from './activate.svelte';
5
+ import { registerShard, activateShard, __resetShardRegistryForTest, } from './lifecycle.svelte';
6
6
  import { __resetViewRegistryForTest } from './registry';
7
7
  describe('ctx.fetch', () => {
8
8
  let originalFetch;
@@ -27,7 +27,7 @@ describe('ctx.fetch', () => {
27
27
  let captured = null;
28
28
  registerShard({
29
29
  manifest: { id: 'test', label: 'test', version: '0.0.0', views: [] },
30
- activate(ctx) { captured = ctx; },
30
+ register(ctx) { captured = ctx; },
31
31
  });
32
32
  await activateShard('test');
33
33
  await captured.fetch('/api/foo');
@@ -42,7 +42,7 @@ describe('ctx.fetch', () => {
42
42
  let captured = null;
43
43
  registerShard({
44
44
  manifest: { id: 'test', label: 'test', version: '0.0.0', views: [] },
45
- activate(ctx) { captured = ctx; },
45
+ register(ctx) { captured = ctx; },
46
46
  });
47
47
  await activateShard('test');
48
48
  await captured.fetch('https://other.example.com/api/bar');
@@ -57,7 +57,7 @@ describe('ctx.fetch', () => {
57
57
  let captured = null;
58
58
  registerShard({
59
59
  manifest: { id: 'test', label: 'test', version: '0.0.0', views: [] },
60
- activate(ctx) { captured = ctx; },
60
+ register(ctx) { captured = ctx; },
61
61
  });
62
62
  await activateShard('test');
63
63
  await captured.fetch('api/baz');
@@ -79,7 +79,7 @@ describe('ctx.serverUrl', () => {
79
79
  let captured = null;
80
80
  registerShard({
81
81
  manifest: { id: 'test', label: 'test', version: '0.0.0', views: [] },
82
- activate(ctx) { captured = ctx; },
82
+ register(ctx) { captured = ctx; },
83
83
  });
84
84
  await activateShard('test');
85
85
  expect(captured.serverUrl).toBe('https://example.com');
@@ -89,7 +89,7 @@ describe('ctx.serverUrl', () => {
89
89
  let captured = null;
90
90
  registerShard({
91
91
  manifest: { id: 'test', label: 'test', version: '0.0.0', views: [] },
92
- activate(ctx) { captured = ctx; },
92
+ register(ctx) { captured = ctx; },
93
93
  });
94
94
  await activateShard('test');
95
95
  expect(captured.serverUrl).toBe('');
@@ -110,7 +110,7 @@ describe('ctx.resolveUrl', () => {
110
110
  let captured = null;
111
111
  registerShard({
112
112
  manifest: { id: 'test', label: 'test', version: '0.0.0', views: [] },
113
- activate(ctx) { captured = ctx; },
113
+ register(ctx) { captured = ctx; },
114
114
  });
115
115
  await activateShard('test');
116
116
  expect(captured.resolveUrl('/api/foo')).toBe('https://example.com/api/foo');
@@ -119,7 +119,7 @@ describe('ctx.resolveUrl', () => {
119
119
  let captured = null;
120
120
  registerShard({
121
121
  manifest: { id: 'test', label: 'test', version: '0.0.0', views: [] },
122
- activate(ctx) { captured = ctx; },
122
+ register(ctx) { captured = ctx; },
123
123
  });
124
124
  await activateShard('test');
125
125
  expect(captured.resolveUrl('https://other.example.com/ws')).toBe('https://other.example.com/ws');
@@ -128,7 +128,7 @@ describe('ctx.resolveUrl', () => {
128
128
  let captured = null;
129
129
  registerShard({
130
130
  manifest: { id: 'test', label: 'test', version: '0.0.0', views: [] },
131
- activate(ctx) { captured = ctx; },
131
+ register(ctx) { captured = ctx; },
132
132
  });
133
133
  await activateShard('test');
134
134
  expect(captured.resolveUrl('api/ws')).toBe('https://example.com/api/ws');
@@ -0,0 +1,108 @@
1
+ import type { Shard, ShardContext } from './types';
2
+ /**
3
+ * Reactive registry of every shard known to the host. Keys are shard ids.
4
+ * Populated by `registerShard`.
5
+ */
6
+ export declare const registeredShards: Map<string, Shard>;
7
+ /**
8
+ * Reactive map of shard ids that failed during the lifecycle. Populated
9
+ * by registerAllShards and related operations.
10
+ */
11
+ export interface ShardErrorEntry {
12
+ id: string;
13
+ error: unknown;
14
+ phase: 'register' | 'launch' | 'satellite';
15
+ timestamp: number;
16
+ }
17
+ export declare const erroredShards: Map<string, ShardErrorEntry>;
18
+ /** Read the app id currently bound to this shard, or null. */
19
+ export declare function getShardBinding(shardId: string): string | null;
20
+ /**
21
+ * Update which app's namespace this shard's `ctx.documents` resolves to.
22
+ * Pass `appId` to bind, `null` to unbind. Internal — only the lifecycle
23
+ * module and `apps/lifecycle.ts` call this.
24
+ */
25
+ export declare function rotateShardDocumentNamespace(shardId: string, appId: string | null): void;
26
+ export interface ShardEntry {
27
+ shard: Shard;
28
+ ctx: ShardContext;
29
+ viewIds: Set<string>;
30
+ verbNames: Set<string>;
31
+ /** Cleanup fns from things registered inside `register()`. Disposed only on shard re-register or framework teardown. */
32
+ bootCleanupFns: (() => Promise<void> | void)[];
33
+ /** Per-(shardId, appId) cleanup bags for things registered inside `onAppActivate`. Keyed by appId. */
34
+ appCleanupBags: Map<string, (() => Promise<void> | void)[]>;
35
+ /** Active appId during `onAppActivate` invocation, so register sites can route disposers to the right bag. */
36
+ activeAppId: string | null;
37
+ }
38
+ export declare function __setScopeResolver(resolver: (() => 'tenant' | 'project') | null): void;
39
+ /**
40
+ * Build a ShardContext for the given shard. The ctx is permanent for the
41
+ * shard's lifetime; the same instance is passed to `register`, every
42
+ * `onAppActivate`/`onAppDeactivate`, and every auxiliary hook.
43
+ *
44
+ * `entry` tracks cleanup bags. When the shard is inside an `onAppActivate`
45
+ * call, register sites route disposers to the per-app bag (keyed by
46
+ * `entry.activeAppId`); otherwise they go to the boot bag.
47
+ */
48
+ export declare function buildShardContext(shard: Shard, entry: ShardEntry): ShardContext;
49
+ export declare const shardEntries: Map<string, ShardEntry>;
50
+ export declare const activeShards: Map<string, Shard>;
51
+ /**
52
+ * Run `register(ctx)` on every registered shard. Idempotent — calling on
53
+ * an already-entered shard is a no-op. Errors are recorded in
54
+ * `erroredShards` with phase 'register'; one failure does not block others.
55
+ */
56
+ export declare function registerAllShards(): Promise<void>;
57
+ export declare function runAppActivate(shardId: string, appId: string): Promise<void>;
58
+ export declare function runAppDeactivate(shardId: string, appId: string): Promise<void>;
59
+ /**
60
+ * Tear down the active entry for a shard and rebuild it from the current
61
+ * `registeredShards.get(id)` value. Used by `registerShard` when replacing
62
+ * an existing shard with a fresh module (package update, dev hot-reload).
63
+ *
64
+ * Fires `onAppDeactivate` for every bound app, calls `deactivate?.()`,
65
+ * flushes all cleanup bags, builds a fresh ctx, then re-runs `register()`.
66
+ * Caller is responsible for re-invoking `runAppActivate` for any apps
67
+ * currently active that require this shard.
68
+ */
69
+ export declare function rebuildShardEntry(shardId: string): Promise<void>;
70
+ /**
71
+ * Register (or re-register) a shard. Records the shard in `registeredShards`.
72
+ * If the shard is already active (in `shardEntries`), triggers a hot-swap
73
+ * via `rebuildShardEntry` so the new module replaces the old one cleanly.
74
+ */
75
+ export declare function registerShard(shard: Shard): void;
76
+ /** True if the shard has been registered AND its register() has run. */
77
+ export declare function isActive(id: string): boolean;
78
+ /** Return the ShardContext for an active shard, or undefined. */
79
+ export declare function getShardContext(id: string): ShardContext | undefined;
80
+ /**
81
+ * Enumerate every view declared as `standalone` across the currently
82
+ * registered/active shards.
83
+ */
84
+ export declare function listStandaloneViews(): Array<{
85
+ shardId: string;
86
+ viewId: string;
87
+ label: string;
88
+ }>;
89
+ /** Test-only reset. */
90
+ export declare function __resetLifecycleForTest(): void;
91
+ /**
92
+ * Test-only reset for the full shard registry. Wipes all live entries,
93
+ * registered shards, and error records.
94
+ */
95
+ export declare function __resetShardRegistryForTest(): void;
96
+ /**
97
+ * @deprecated v2 compat shim — use `registerAllShards()` to run register
98
+ * for every registered shard. This shim activates a single shard by
99
+ * invoking its register hook directly. Retained for test fixtures during
100
+ * the migration; Phase 7 sweeps callers.
101
+ */
102
+ export declare function activateShard(id: string): Promise<void>;
103
+ /**
104
+ * @deprecated v2 compat shim — in v3, shards stay alive for the whole
105
+ * session. This shim performs a full teardown of the entry (for tests
106
+ * that explicitly want to verify cleanup paths).
107
+ */
108
+ export declare function deactivateShard(id: string): void;