@jskit-ai/agent-docs 0.1.250 → 0.1.252

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 (39) hide show
  1. package/guide/agent/app-extras/assistant-conversation.md +267 -53
  2. package/guide/agent/app-extras/assistant.md +6 -1
  3. package/guide/agent/app-extras/realtime.md +59 -3
  4. package/guide/agent/app-setup/authentication.md +58 -0
  5. package/guide/agent/app-setup/existing-application-migration.md +7 -1
  6. package/package.json +1 -1
  7. package/patterns/feature-package/example/booking-engine/package.json +1 -1
  8. package/patterns/minimal-foundation/example/package.json +3 -3
  9. package/patterns/shell-foundation/example/package.json +4 -4
  10. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  11. package/reference/autogen/KERNEL_MAP.md +6 -0
  12. package/reference/autogen/PATTERN_INDEX.md +39 -39
  13. package/reference/autogen/packages/assistant-core.md +29 -9
  14. package/reference/autogen/packages/auth-provider-local-core.md +30 -1
  15. package/reference/autogen/packages/auth-provider-local-db-core.md +6 -0
  16. package/reference/autogen/packages/crud-core.md +2 -2
  17. package/reference/autogen/packages/kernel.md +11 -0
  18. package/reference/autogen/packages/realtime.md +13 -2
  19. package/reference/autogen/packages/shell-web.md +6 -0
  20. package/reference/autogen/packages/users-web.md +4 -0
  21. package/skills/jskit/references/existing-application-migration.md +7 -1
  22. package/skills/jskit/references/pattern-index.md +39 -39
  23. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +3 -3
  24. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +4 -4
  25. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
  26. package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
  27. package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
  28. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
  29. package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
  30. package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +7 -0
  31. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
  32. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
  33. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
  34. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
  35. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
  36. package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +12 -3
  37. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsSignInMethodsSection.vue +67 -0
  38. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
  39. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
@@ -139,8 +139,10 @@ Local functions
139
139
  - `messageScrollKey(message = null)`
140
140
  - `clearUserScrollIntent()`
141
141
  - `resumePendingTailFollow()`
142
- - `markUserScrollIntent()`
142
+ - `markUserScrollIntent({ upward = false } = {})`
143
143
  - `markKeyboardScrollIntent(event = {})`
144
+ - `rememberTouch(event = {})`
145
+ - `markTouchScrollIntent(event = {})`
144
146
  - `scrollToLatestMessageAfterLayout({ behavior = "auto", force = false } = {})`
145
147
  - `queueInitialBottomScroll()`
146
148
  - `queueLiveBottomScroll({ force = false } = {})`
@@ -355,9 +357,10 @@ Exports
355
357
  - `bindClaudeConversationAccount(entry, { identity, providerId, allowAccountChange = false, stop, save })`
356
358
  - `claudePlanUsage(value)`
357
359
  - `claudeCatalogueModels(initialization)`
358
- - `createClaudeAccountQueries({ createProcess, accountIdentity, processes = () => [], isClosing = () => false })`
360
+ - `createClaudeAccountQueries({ createProcess, accountIdentity, configRoot, processes = () => [], isClosing = () => false })`
359
361
  - `createClaudeCodeProcess({ command = "claude", execution = createLocalConversationExecution(), env = process.env, workdir, onEvent, onControlRequest, onFailure, onStarted, executionLimits, signal, commandWrapper, initializationTimeoutMs = 30_000, onInitializationProgress, ...options } = {})`
360
362
  Local functions
363
+ - `fileRevision(file)`
361
364
  - `readNativeClaudeCodeAuthStatus({ env, credentialHome, command, commandRunner, signal })`
362
365
  - `claudeCodeAuthStatus(result)`
363
366
  - `claudePlanUsageVerified(value)`
@@ -381,6 +384,7 @@ Local functions
381
384
  - `now()`
382
385
  - `hasPendingClaudeStartup(entry)`
383
386
  - `nativeWorkSettled(entry)`
387
+ - `runsNativeWork(entry)`
384
388
 
385
389
  ### `src/server/conversation/codexAuthPreflight.js`
386
390
  Exports
@@ -408,7 +412,7 @@ Exports
408
412
  - `codexAppServerTurnSettings({ effectiveSettings, cwd = "", effort = "", model = "", approvalPolicy, reasoningSummary, sandboxPolicy, externalSandbox = false } = {})`
409
413
  - `codexInteractiveArguments({ command, threadId = "", remoteEndpoint = "", model, effort, disableStartupUpdates = false, bypassApprovalsAndSandbox = false, bypassHookTrust = false } = {})`
410
414
  - `codexAppServerProjectHookTrustConfig(provider, cwd = "", { persist = false } = {})`
411
- - `prepareCodexModelCatalog({ command, runtimeDir, bundled = false, signal, additionalModels = [] })`
415
+ - `prepareCodexModelCatalog({ command, runtimeDir, bundled = false, signal, additionalModels = [], codexHome = process.env.CODEX_HOME || path.join(os.homedir(), ".codex") })`
412
416
  - `readCodexModelContextWindow({ runtimeDir, model } = {})`
413
417
  - `codexAppServerTextHasControlCharacters(value = "")`
414
418
  - `createCodexAppServerIsolation({ clientName = "jskit", minimumVersion = "0.151.0", disabledFeatures = DISABLED_FEATURES, limits: { userAgentMaxLength = 512, mcpServerMaxCount = 128, mcpServerNameMaxLength = 256, configResponseMaxBytes = 256 * 1024, hookMaxCount = 256, hookErrorMaxCount = 256, hookFieldMaxLength = 2048, hookFingerprintMaxLength = 256 * 1024, hookResponseMaxBytes = 512 * 1024 } = {}, createError = codexAppServerIsolationPolicyError } = {})`
@@ -428,6 +432,7 @@ Exports
428
432
  - `codexAuthOutputRequiresReconnect(output = "")`
429
433
  - `CODEX_APP_SERVER_ACCOUNT_ID_MAX_LENGTH`
430
434
  Local functions
435
+ - `codexModelCatalogRevision({ command, codexHome, bundled, additionalModels })`
431
436
  - `isPlainRecord(value)`
432
437
  - `deepFreezeCodexAppServerHelperConfig(value)`
433
438
  - `codexAppServerIsolationPolicyError(message = "", details = {})`
@@ -435,7 +440,7 @@ Local functions
435
440
 
436
441
  ### `src/server/conversation/codexConversations.js`
437
442
  Exports
438
- - `createCodexConversationCommands({ checkpoint, codexAppServerConversationMessageId, codexAppServerStreamMessage, conversationPreparation, ensureCodexAppServerProviderForActiveTurn, errorPrefix, helperLifecycle, helperOwnershipError, interruptFailedCode, namespace, providerSessions, sessionConnection, ensureSessionProvider, steerFailedCode, turnOutcomes })`
443
+ - `createCodexConversationCommands({ checkpoint, codexAppServerConversationMessageId, codexAppServerStreamMessage, conversationPreparation, ensureCodexAppServerProviderForActiveTurn, errorPrefix, helperLifecycle, helperOwnershipError, interruptFailedCode, namespace, providerSessions, ensureSessionProvider, borrowSessionProvider, steerFailedCode, turnOutcomes })`
439
444
 
440
445
  ### `src/server/conversation/codexConversationStore.js`
441
446
  Exports
@@ -489,6 +494,7 @@ Exports
489
494
  - `codexAppServerUserMessageText(item = {})`
490
495
  Local functions
491
496
  - `nonNegativeInteger(value)`
497
+ - `codexAppServerSignedOutText(text = "")`
492
498
  - `codexAppServerTextInputText(input = {})`
493
499
  - `codexAppServerHookPromptText(item = {})`
494
500
  - `codexAppServerFinalEventText(notification = {}, event = null, payload = {})`
@@ -539,6 +545,13 @@ Local functions
539
545
  - `restoreCompactedHistory(body, { destination, historyPath, codexHome, signal, maxRequestBytes })`
540
546
  - `forwardedHeaders(input)`
541
547
 
548
+ ### `src/server/conversation/codexHomeStorage.js`
549
+ Exports
550
+ - `codexDisabledProcessFeatureArguments()`
551
+ - `codexHomeDisposablePaths(codexHome, { retired = false } = {})`
552
+ Local functions
553
+ - `directoryNames(directory)`
554
+
542
555
  ### `src/server/conversation/codexMessageCommands.js`
543
556
  Exports
544
557
  - `createCodexMessageCommands({ output, journal, recovery, threadStatus, selection, observer, delivery, promptDeliveries: codexAppServerPromptDeliveries, createRuntime, debugError, debugLog, errorPrefix, messageIdPrefix, messageMetadata, namespace, providerSessions, recoverAdmission, steerFailedCode, turnAlreadyRunningError, turnState })`
@@ -594,6 +607,7 @@ Exports
594
607
  - `codexAppServerHelperHomeDir(runtimeDir = "")`
595
608
  - `codexAppServerHelperWorkspaceDir(runtimeDir = "")`
596
609
  - `codexAppServerProcessCwd({ executionRoot = "", runtimeDir = "", workdir = "" } = {})`
610
+ - `removeCodexAppServerRuntimeDir(runtimeDir = "")`
597
611
  - `codexAppServerRuntimeIdentity(runtime = {})`
598
612
  - `normalizeCodexAppServerTerminalEnv(terminalEnv = {})`
599
613
  - `codexAppServerCommandBaseEnv({ env = process.env, terminalEnv = {} } = {})`
@@ -621,7 +635,6 @@ Local functions
621
635
  - `codexAppServerUnixEndpoint(socketPath = "")`
622
636
  - `codexAppServerProjectTrustOverride(workdir = "")`
623
637
  - `codexAppServerRuntimeDirIsManaged(runtimeDir = "")`
624
- - `removeCodexAppServerRuntimeDir(runtimeDir = "")`
625
638
  - `removeCodexAppServerMetadataTemps(runtimeDir = "")`
626
639
  - `codexAppServerRuntimeCleanupCanSkip(error)`
627
640
  - `codexHistoryAdapterUrlIsValid(baseUrl, token)`
@@ -671,7 +684,7 @@ Local functions
671
684
  - `codexAppServerThreadRequestParams(params = {}, threadEnv = {})`
672
685
  - `codexControlProbeCommand(keys, marker)`
673
686
  - `codexAppServerThreadInventoryError(errorCode, label, detail)`
674
- - `listBoundedCodexAppServerThreadIds({ ancestorThreadId = "", archived = false, client, cwd = "", errorCode = "", label = "", requestLabel = "", runRequest, signal = null, sourceKinds = ["appServer"], state, verifyCwd = false } = {})`
687
+ - `listBoundedCodexAppServerThreadIds({ ancestorThreadId = "", archived = false, client, cwd = "", errorCode = "", findThreadId = "", label = "", requestLabel = "", runRequest, signal = null, sourceKinds = ["appServer"], state, verifyCwd = false } = {})`
675
688
  - `codexPlanUsage(limits = {})`
676
689
  - `normalizeAgentThread(value = {})`
677
690
  - `normalizeAgentTurn(value = {})`
@@ -679,11 +692,14 @@ Local functions
679
692
  ### `src/server/conversation/codexProviderOwner.js`
680
693
  Exports
681
694
  - `codexAppServerOwnedRuntimeKey(providerKey = "", providerOptions = {})`
695
+ - `releaseSupersededCodexRuntime(runtimeDir = "")`
682
696
  - `codexAppServerRuntimeStopWasVerified(result = {})`
683
697
  - `directoryExists(filePath = "")`
684
698
  - `createCodexAppServerProviderOwner({ runtimeRoot = "", assertOpen: assertApplicationOpen = () => {}, onRecoveryEvent = () => {}, debugLog = () => {}, debugError = error => error, providerFactory = null, prepareNativeHost = () => ({}), runtimeBusyCode = "codex_app_server_runtime_busy", exitUnverifiedCode = "codex_runtime_exit_unverified", requiredStopCode = "codex_runtime_exit_unverified", runtimeCloseError = "Codex app-server runtime close failed.", transientIdleMs = 60_000 } = {})`
685
699
  Local functions
686
700
  - `withRuntimeLifecycle(runtimeKey, operation)`
701
+ - `nativeRequest(client, method, params)`
702
+ - `runningNativeThreads(peers)`
687
703
 
688
704
  ### `src/server/conversation/codexProviderSelection.js`
689
705
  Exports
@@ -720,7 +736,7 @@ Exports
720
736
 
721
737
  ### `src/server/conversation/codexRuntimeLifecycle.js`
722
738
  Exports
723
- - `createCodexRuntimeLifecycle({ pendingWork, observer, checkManagedConnection, providerSessions, helperLifecycle, captureContext, runInContext, debugLog, debugError, closingError = null })`
739
+ - `createCodexRuntimeLifecycle({ pendingWork, observer, checkManagedConnection, providerSessions, helperLifecycle, captureContext, runInContext, continueGoalAfterAccountChange = null, debugLog, debugError, closingError = null })`
724
740
 
725
741
  ### `src/server/conversation/codexSessionCleanup.js`
726
742
  Exports
@@ -740,7 +756,7 @@ Exports
740
756
 
741
757
  ### `src/server/conversation/codexTurn.js`
742
758
  Exports
743
- - `createCodexAppServerRunOwner({ namespace = normalizeCodexRunText, normalizeRunState = normalizeCodexAppServerRunState, debugLog = () => {}, debugError = error => normalizeCodexRunText(error?.message || error), createRuntime, createStore, publish = async () => null, acquireProvider = async () => null, providerSessions = null, serverClosingError = null, helperThreads = null, modelCatalogCacheMs = 30_000, conversationPreparation = null, storeReadError = "The session store does not support agent-run reads.", sessionIdRequiredError = "A session ID is required.", turnClaimsUnsupportedError = "The session runtime does not support Codex turn claims.", turnAlreadyRunningError = "Codex is already working on this session.", messageIdPrefix = "codex:", idlePublishPayload = null, checkpoint = async () => null, messageMetadata = {}, persistCommentary = true, deliveryStateMetadataKey = "assistant_delivery", hasRuntime = () => true, recoverAdmission = null, admissionTaskFinished = () => false, outcomeNotice = async () => null, resultDeliveryFailureMessage = ({ error = "" } = {}) => { const detail = normalizeCodexRunText(error); if (!detail) return "Codex app-server finished this turn, but the assistant result text was not received."; const punctuation = [".", "!", "?"].some(character => detail.endsWith(character)) ? "" : "."; return "Codex completed, but its response could not be processed: " + detail + punctuation; }, orphanedPromptMessage = "The application restarted before Codex confirmed the message. Your message is safe; retry it.", onNotificationSignal = async () => null, captureContext = () => null, runInContext = (_context, operation) => operation(), notificationQueue = null, activeReconcileMs = 2000, finalizingGraceMs = 10000, finalizingGraceAfterHistoryRead = false, failureDetailGraceMs = 0, steerFailedCode = "codex_turn_steer_failed", interruptFailedCode = "codex_turn_interrupt_failed", errorPrefix = "" } = {})`
759
+ - `createCodexAppServerRunOwner({ namespace = normalizeCodexRunText, normalizeRunState = normalizeCodexAppServerRunState, debugLog = () => {}, debugError = error => normalizeCodexRunText(error?.message || error), createRuntime, createStore, publish = async () => null, acquireProvider = async () => null, providerSessions = null, serverClosingError = null, helperThreads = null, modelCatalogCacheMs = 30_000, conversationPreparation = null, storeReadError = "The session store does not support agent-run reads.", sessionIdRequiredError = "A session ID is required.", turnClaimsUnsupportedError = "The session runtime does not support Codex turn claims.", turnAlreadyRunningError = "Codex is already working on this session.", messageIdPrefix = "codex:", idlePublishPayload = null, checkpoint = async () => null, messageMetadata = {}, persistCommentary = true, deliveryStateMetadataKey = "assistant_delivery", hasRuntime = () => true, recoverAdmission = null, admissionTaskFinished = () => false, outcomeNotice = async () => null, resultDeliveryFailureMessage = ({ error = "" } = {}) => { const detail = normalizeCodexRunText(error); if (!detail) return "Codex app-server finished this turn, but the assistant result text was not received."; const punctuation = [".", "!", "?"].some(character => detail.endsWith(character)) ? "" : "."; return "Codex completed, but its response could not be processed: " + detail + punctuation; }, orphanedPromptMessage = "The application restarted before Codex confirmed the message. Your message is safe; retry it.", onNotificationSignal = async () => null, captureContext = () => null, runInContext = (_context, operation) => operation(), // Resumes a goal an account change paused, once the previous account's // runtime has stopped: `(sessionId, { threadId })`. Without it the goal stays // paused for the person to resume. continueGoalAfterAccountChange = null, notificationQueue = null, activeReconcileMs = 2000, finalizingGraceMs = 10000, finalizingGraceAfterHistoryRead = false, failureDetailGraceMs = 0, steerFailedCode = "codex_turn_steer_failed", interruptFailedCode = "codex_turn_interrupt_failed", errorPrefix = "" } = {})`
744
760
  - `CODEX_APP_SERVER_RUN_STATE`
745
761
  - `normalizeCodexAppServerRunState`
746
762
  - `codexAppServerRunStateIsActive`
@@ -944,7 +960,7 @@ Exports
944
960
  - `retireOpenCodeConversationHistory(storageClient, controlClient, binding, options = {})`
945
961
  - `openCodeAssistantMessageText(message = {})`
946
962
  - `OPENCODE_RESPONSE_LIMIT_BYTES`
947
- - `createOpenCodeServerClient({ allowAttachmentDirectories = false, baseUrl = "", directory = "", fetchImpl = globalThis.fetch, password = "", username = "opencode" } = {})`
963
+ - `createOpenCodeServerClient({ allowAttachmentDirectories = false, baseUrl = "", defaultDirectory = "", directory = "", fetchImpl = globalThis.fetch, instances = { addressed: new Map(), sequence: 0 }, password = "", username = "opencode" } = {})`
948
964
  - `readBoundedResponse(response, limitBytes = OPENCODE_RESPONSE_LIMIT_BYTES)`
949
965
  Local functions
950
966
  - `record(value)`
@@ -997,6 +1013,7 @@ Exports
997
1013
  - `createOpenCodeConversationPlugin`
998
1014
  Local functions
999
1015
  - `availableLoopbackPort()`
1016
+ - `openCodeExitReason(logs)`
1000
1017
  - `waitForOpenCodeReady({ client, expectedVersion = OPENCODE_EXPECTED_VERSION, processHandle, timeoutMs = OPENCODE_READY_TIMEOUT_MS, signal } = {})`
1001
1018
  - `actionPermission(action)`
1002
1019
  - `agentPermission(ask, nativeTools, tools)`
@@ -1235,6 +1252,8 @@ Exports
1235
1252
  - `createCodexAccountReader`
1236
1253
  - `createCodexAppServerIsolation`
1237
1254
  - `readCodexToolFreeConfiguration`
1255
+ - `codexDisabledProcessFeatureArguments`
1256
+ - `codexHomeDisposablePaths`
1238
1257
 
1239
1258
  ### `src/server/hosts/codexEvents.js`
1240
1259
  Exports
@@ -1843,6 +1862,7 @@ Local functions
1843
1862
  Exports
1844
1863
  - None
1845
1864
  Local functions
1865
+ - `cancelMessage(id)`
1846
1866
  - `accept()`
1847
1867
 
1848
1868
  ### `fixtures/responsive-assistant/main.js`
@@ -28,6 +28,10 @@ Local functions
28
28
  - `serializeSessions(sessions)`
29
29
  - `parseRecovery(content)`
30
30
  - `serializeRecovery(records)`
31
+ - `parseIdentities(content)`
32
+ - `serializeIdentities(identities)`
33
+ - `parseOAuthAttempts(content)`
34
+ - `serializeOAuthAttempts(attempts)`
31
35
  - `readText(filePath)`
32
36
  - `writeAtomic(filePath, content)`
33
37
  - `encodeJournalContent(content)`
@@ -53,6 +57,15 @@ Exports
53
57
  - `normalizePasswordStrategy`
54
58
  - `verifyPassword`
55
59
 
60
+ ### `src/server/lib/oauth.js`
61
+ Exports
62
+ - `createOAuthClients({ logger = null } = {})`
63
+ - `resolveOAuthProviders(env = {})`
64
+ Local functions
65
+ - `signInError(statusCode, message, { code, provider = null })`
66
+ - `unverifiedSignIn()`
67
+ - `displayNameFrom(source = {})`
68
+
56
69
  ### `src/server/lib/passwords.js`
57
70
  Exports
58
71
  - `hashPassword(password)`
@@ -83,6 +96,7 @@ Local functions
83
96
  - `isDevAuthSession(session)`
84
97
  - `isAuthenticatingSession(session)`
85
98
  - `normalizeDisplayName(value, email)`
99
+ - `hasPassword(user)`
86
100
  - `createId(prefix)`
87
101
  - `safeRequestCookies(request)`
88
102
  - `unauthenticatedAuthResult(clearSession = false)`
@@ -120,4 +134,19 @@ Exports
120
134
  Local functions
121
135
  - `resolveStoreDir(env, appRoot)`
122
136
  - `resolveSessionSecret(env, { storeDir, isProduction })`
123
- - `resolveAppPublicUrl(env, { recoverySender })`
137
+ - `resolveAppPublicUrl(env, { recoverySender, oauthProviders })`
138
+
139
+ ### test-support
140
+
141
+ ### `test-support/oauthHarness.js`
142
+ Exports
143
+ - `APP_URL`
144
+ - `ATTEMPT_COOKIE`
145
+ - `approveAtProvider(service, { provider = "google", returnTo = "/home", cookies = {}, link = false } = {})`
146
+ - `createService({ backend, oauthProviders, profileProjector = null })`
147
+ - `oidcProviderEntry(issuer, { id = "google", label = "Google" } = {})`
148
+ - `sessionCookies(session)`
149
+ - `startFakeGitHub({ user = { id: 4242, login: "ada", name: "Ada Lovelace" }, emails } = {})`
150
+ - `startOidcProvider({ account } = {})`
151
+ Local functions
152
+ - `readBody(req)`
@@ -29,6 +29,8 @@ Local functions
29
29
  - `mapUser(row)`
30
30
  - `mapSession(row)`
31
31
  - `mapRecovery(row)`
32
+ - `mapIdentity(row)`
33
+ - `mapOAuthAttempt(row)`
32
34
  - `userInsert(input = {})`
33
35
  - `sessionInsert(input = {})`
34
36
  - `recoveryInsert(input = {})`
@@ -48,3 +50,7 @@ Exports
48
50
  ### `migrations/auth_local_db_initial.cjs`
49
51
  Exports
50
52
  - None
53
+
54
+ ### `migrations/auth_local_db_oauth.cjs`
55
+ Exports
56
+ - None
@@ -45,7 +45,7 @@ Local functions
45
45
 
46
46
  ### `src/server/defineCrudJsonApiFeature.js`
47
47
  Exports
48
- - `defineCrudJsonApiFeature({ resource, id = "", capability = "", surface, ownershipFilter = "", relativePath = "", internal = false, routes = true, listFilterQueryValidator = null, searchSchema = null, permissions = null, scope = {}, requires = {}, decorateRepository = null, decorateService = null, operationLifecycle = {}, operationInputs = {}, actions = {}, operations = undefined } = {})`
48
+ - `defineCrudJsonApiFeature({ resource, id = "", capability = "", surface, ownershipFilter = "", relativePath = "", internal = false, routes = true, listFilterQueryValidator = null, searchSchema = null, permissions = null, scope = {}, requires = {}, decorateRepository = null, decorateService = null, operationLifecycle = {}, operationInputs = {}, actions = {}, operations = undefined, realtimeAudience = "event_scope" } = {})`
49
49
  Local functions
50
50
  - `normalizeAccess(resource = {})`
51
51
  - `normalizeScope(scope = {})`
@@ -74,7 +74,7 @@ Local functions
74
74
  ### `src/server/jsonApiModule/actions.js`
75
75
  Exports
76
76
  - `assertCrudOperationName(operation = "")`
77
- - `createCrudJsonApiActions({ namespace, resource, repository = null, service, surface, permissionForOperation, permissionForAction = permissionForOperation, operations = CRUD_OPERATION_NAMES, scopeInputValidator = null, scopeInputKeys = [], listFilterQueryValidator = null, operationLifecycle = {}, operationInputs = {}, actions: additionalActionDefinitions = {}, dependencies = {} } = {})`
77
+ - `createCrudJsonApiActions({ namespace, resource, repository = null, service, surface, permissionForOperation, permissionForAction = permissionForOperation, operations = CRUD_OPERATION_NAMES, scopeInputValidator = null, scopeInputKeys = [], listFilterQueryValidator = null, operationLifecycle = {}, operationInputs = {}, actions: additionalActionDefinitions = {}, dependencies = {}, realtimeAudience = "event_scope" } = {})`
78
78
  - `normalizeCrudOperationLifecycle(value = {})`
79
79
  Local functions
80
80
  - `isRecord(value)`
@@ -60,6 +60,12 @@ Exports
60
60
  - `resolveLinkPath`
61
61
  - `normalizePathname`
62
62
 
63
+ ### `shared/support/clientBuild.js`
64
+ Exports
65
+ - `CLIENT_BUILD_META_NAME`
66
+ - `clientBuildIdFromHtml(html = "")`
67
+ - `pageClientBuildId(documentObject = globalThis.document)`
68
+
63
69
  ### `shared/support/deepFreeze.js`
64
70
  Exports
65
71
  - `deepFreeze(value, seen = new WeakSet())`
@@ -926,6 +932,10 @@ Local functions
926
932
  - `normalizeConfigObject(value)`
927
933
  - `loadConfigModuleAtPath(absolutePath)`
928
934
 
935
+ ### `server/support/clientBuild.js`
936
+ Exports
937
+ - `readServedClientBuildId({ appRoot } = {})`
938
+
929
939
  ### `server/support/defaultMissingHandler.js`
930
940
  Exports
931
941
  - `defaultMissingHandler(_request, reply)`
@@ -960,6 +970,7 @@ Exports
960
970
  - `resolveRequiredAppRoot`
961
971
  - `toPosixPath`
962
972
  - `tryAcquireExclusiveFileLock`
973
+ - `readServedClientBuildId`
963
974
 
964
975
  ### `server/support/path.js`
965
976
  Exports
@@ -44,6 +44,7 @@ Exports
44
44
  - `resolveRealtimeClientConfig({ env = {}, mobile = null } = {})`
45
45
  Local functions
46
46
  - `createRealtimeClient({ config, loggerInput } = {})`
47
+ - `trackServedClientBuild(socket, logger)`
47
48
 
48
49
  ### `src/client/runtime.js`
49
50
  Exports
@@ -56,7 +57,7 @@ Exports
56
57
  - `createAudienceContributors()`
57
58
  - `createSocketRequest(socket)`
58
59
  - `realtimeAuthenticationRequired(authService = null)`
59
- - `revalidateSocket({ socket, authService, audiences = null, request })`
60
+ - `revalidateSocket({ socket, authService, audiences = null, request, authenticateRequest })`
60
61
  - `registerSocketAudienceBootstrap({ io, logger, authService = null, audiences = null })`
61
62
  - `resolveAudienceTargets(audience, event, { database = null, logger })`
62
63
  Local functions
@@ -67,11 +68,12 @@ Local functions
67
68
  - `resolveScopeWorkspaceId(scope = {})`
68
69
  - `resolveScopeUserId(scope = {})`
69
70
  - `roomForScope(scope = {})`
71
+ - `isScopeRoom(room)`
70
72
  - `applyAudiencePreset(preset, { event, rooms, flags, logger })`
71
73
  - `addAudienceRooms(selection, state)`
72
74
  - `collectUserIds(rows)`
73
75
  - `parseCookieHeader(value = "")`
74
- - `resolveSocketActor(authService, socket, request = createSocketRequest(socket))`
76
+ - `resolveSocketActor(authService, socket, request = createSocketRequest(socket), authenticateRequest = (value) => authService.authenticateRequest(value))`
75
77
  - `authenticationRequiredError()`
76
78
  - `rememberSocketActorId(socket, actorId)`
77
79
  - `registerRequiredSocketAuthentication({ io, logger, authService })`
@@ -82,6 +84,7 @@ Exports
82
84
  - `createRealtimeDelivery({ io, database = null, logger, authService = null, audiences = null })`
83
85
  Local functions
84
86
  - `publicRealtimePayload(event)`
87
+ - `createSharedAuthentication(authService)`
85
88
 
86
89
  ### `src/server/RealtimeProvider.js`
87
90
  Exports
@@ -108,6 +111,14 @@ Local functions
108
111
  - `resolveHttpServer({ httpServer = null, fastify = null } = {})`
109
112
  - `buildSocketIoRedisAdapterKey(redisNamespace = "")`
110
113
 
114
+ ### `src/server/servedClientBuild.js`
115
+ Exports
116
+ - `announceServedClientBuild({ io, appRoot, logger })`
117
+
118
+ ### `src/shared/servedClientBuild.js`
119
+ Exports
120
+ - `SERVED_CLIENT_BUILD_EVENT`
121
+
111
122
  ### patterns
112
123
 
113
124
  ### `patterns/realtime-application/example/src/placement.js`
@@ -52,6 +52,12 @@ Exports
52
52
  - `normalizeBootstrapPayloadHandler`
53
53
  - `resolveBootstrapErrorStatusCode`
54
54
 
55
+ ### `src/client/clientUpdate/runtime.js`
56
+ Exports
57
+ - `createShellClientUpdateRuntime({ errorRuntime, reload, pageBuildId = pageClientBuildId(), appName = loadedAppName() } = {})`
58
+ Local functions
59
+ - `loadedAppName(documentObject = globalThis.document)`
60
+
55
61
  ### `src/client/components/ShellErrorHost.vue`
56
62
  Exports
57
63
  - None
@@ -143,6 +143,10 @@ Exports
143
143
  Exports
144
144
  - None
145
145
 
146
+ ### `patterns/account-settings/example/src/components/account/settings/AccountSettingsSignInMethodsSection.vue`
147
+ Exports
148
+ - None
149
+
146
150
  ### `patterns/account-settings/example/src/pages/account/index.vue`
147
151
  Exports
148
152
  - None
@@ -62,7 +62,13 @@ or operation boundary. A Feature declares stable named `requires`, optional
62
62
  inputs, and `provides`; `setup()` receives those values directly and returns
63
63
  only the promised outputs. Named actions capture the exact feature APIs they
64
64
  need. Register structural catalogue entries during `setup()` and reserve
65
- `boot()` for long-lived work that starts after composition.
65
+ `boot()` for long-lived work that starts after composition. `shutdown()` stops
66
+ that work. The runtime shuts Features down in reverse order and keeps going
67
+ after one fails; it then rejects with an `AggregateError` holding one error per
68
+ failed Feature, each naming its `providerId`. While shutdown runs,
69
+ `diagnostics().providerShutdowns` lists every shutdown with its status
70
+ (`stopping`, `stopped` or `failed`) and duration, so a host can log which one is
71
+ slow.
66
72
 
67
73
  Capability ids, action ids, routes, events, resources, and placements are
68
74
  stable identities. They are not permission to fetch arbitrary dependencies by