@abraca/dabra 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -748,6 +748,32 @@ declare class AbracadabraClient {
748
748
  adminBackupDump(opts?: {
749
749
  includeAudit?: boolean;
750
750
  }): Promise<Blob>;
751
+ /**
752
+ * List every registered config field with current value + origin
753
+ * (`default` / `env` / `global_override` / `route_override`). Requires
754
+ * elevated role.
755
+ */
756
+ adminConfigList(): Promise<AdminConfigField[]>;
757
+ /** Read a single config field by dotted path (e.g. `"access.authenticated"`). */
758
+ adminConfigGet(path: string): Promise<AdminConfigField>;
759
+ /**
760
+ * Set a runtime override on a config field. The field must be marked
761
+ * `runtime_mutable = true` in the registry; immutable fields return a
762
+ * schema error. Persists to the `settings_overrides` table.
763
+ */
764
+ adminConfigSet(path: string, value: unknown): Promise<AdminConfigField>;
765
+ /**
766
+ * Clear a runtime override and revert the field to its env/TOML/default
767
+ * base value. Returns `true` when an override was actually removed.
768
+ */
769
+ adminConfigUnset(path: string): Promise<boolean>;
770
+ /**
771
+ * Diagnostic dump of every `ABRA_*` env var the running process saw at
772
+ * boot, mapped to its config path. Use this to debug
773
+ * "I set this in `.env` but the server reports a different value".
774
+ * Secrets are redacted (`value: null`, `redacted: true`).
775
+ */
776
+ adminConfigEnvSnapshot(): Promise<EnvSnapshotResponse>;
751
777
  /** List snapshot metadata for a document. */
752
778
  listSnapshots(docId: string, opts?: {
753
779
  limit?: number;
@@ -1697,6 +1723,64 @@ interface AuditVerifyResult {
1697
1723
  reason: string;
1698
1724
  };
1699
1725
  }
1726
+ /**
1727
+ * Where the current value of a config field came from.
1728
+ *
1729
+ * * `default` — compiled-in default; nobody touched it.
1730
+ * * `env` — set at startup by an `ABRA_*` env var.
1731
+ * * `global_override` — admin runtime override via `/admin/config`.
1732
+ * * `route_override` — per-route override (Phase 3).
1733
+ */
1734
+ type AdminConfigOriginKind = "default" | "env" | "global_override" | "route_override";
1735
+ /** One entry returned by `GET /admin/config` and `GET /admin/config/fields/:path`. */
1736
+ interface AdminConfigField {
1737
+ path: string;
1738
+ section: string;
1739
+ description: string;
1740
+ env_var: string;
1741
+ runtime_mutable: boolean;
1742
+ value: unknown;
1743
+ origin_kind: AdminConfigOriginKind;
1744
+ /** Provenance — present only when origin_kind is a `*_override`. */
1745
+ set_at?: number;
1746
+ set_by?: string;
1747
+ route?: string;
1748
+ }
1749
+ /**
1750
+ * One row from `GET /admin/config/env-snapshot.items[]`. Reports whether
1751
+ * each registry-known `ABRA_*` env var was set in the running process at
1752
+ * boot, with secrets reported as `value: null` and `redacted: true`.
1753
+ */
1754
+ interface EnvSnapshotItem {
1755
+ env_var: string;
1756
+ path: string;
1757
+ section: string;
1758
+ present: boolean;
1759
+ /** Verbatim env value, or `null` for redacted (secrets) or unset. */
1760
+ value: string | null;
1761
+ redacted: boolean;
1762
+ }
1763
+ /**
1764
+ * One row from `GET /admin/config/env-snapshot.extensions[]`. Extension
1765
+ * overrides (`ABRA_EXT_<name>_<field>`) sit outside the registry and are
1766
+ * reported by name with values inline.
1767
+ */
1768
+ interface EnvSnapshotExtension {
1769
+ env_var: string;
1770
+ value: string;
1771
+ }
1772
+ /**
1773
+ * `GET /admin/config/env-snapshot` response.
1774
+ *
1775
+ * `unknown` lists `ABRA_*` env vars present in the process that don't map
1776
+ * to any registered field — i.e. typos. Operators that see their tweak
1777
+ * land here instead of in `items` know they misspelled the var.
1778
+ */
1779
+ interface EnvSnapshotResponse {
1780
+ items: EnvSnapshotItem[];
1781
+ extensions: EnvSnapshotExtension[];
1782
+ unknown: string[];
1783
+ }
1700
1784
  /** Response of `GET /readyz`. HTTP 200 when ready, 503 when not. */
1701
1785
  interface ReadyzStatus {
1702
1786
  status: "ready" | "unready";
@@ -4465,4 +4549,4 @@ declare function normalizeRootId(id: string | null | undefined, rootDocId: strin
4465
4549
  */
4466
4550
  declare function toPlain(val: unknown): unknown;
4467
4551
  //#endregion
4468
- export { AbracadabraBaseProvider, AbracadabraBaseProviderConfiguration, AbracadabraClient, AbracadabraClientConfig, AbracadabraOutgoingMessageArguments, AbracadabraProvider, AbracadabraProviderConfiguration, AbracadabraWS, AbracadabraWSConfiguration, AbracadabraWebRTC, type AbracadabraWebRTCConfiguration, AbracadabraWebSocketConn, AuditLogEntry, AuditQueryOpts, AuditVerifyResult, AuthFailureContext, AuthFailureReason, AuthMessageType, AuthorizedScope, AwarenessError, BackgroundSyncManager, type BackgroundSyncManagerOptions, BackgroundSyncPersistence, BroadcastChannelSync, CHANNEL_NAMES, ChannelKeyResolver, type ChatChannel, ChatClient, type ChatClientTransport, type MarkReadInput as ChatMarkReadInput, type ChatMessage, type ChatReadCursor, type ChatReadReceipt, type ChatTypingEvent, CloseEvent, CompleteAbracadabraBaseProviderConfiguration, CompleteAbracadabraWSConfiguration, CompleteHocuspocusProviderConfiguration, CompleteHocuspocusProviderWebsocketConfiguration, ConnectionTimeout, Constructable, ConstructableOutgoingMessage, ContentManager, type CreateNotificationInput, CryptoIdentity, CryptoIdentityKeystore, DEFAULT_FILE_CHUNK_SIZE, DEFAULT_ICE_SERVERS, DataChannelRouter, type DeleteMessageInput, DevicePairingChannel, type DevicePairingConfig, DeviceRegistrationService, type DeviceServerStatus, type DeviceTier, type DocEncryptionInfo, DocKeyManager, DocSearchHit, type DocSyncState, type DocumentBlock, DocumentCache, type DocumentCacheOptions, type DocumentContent, DocumentManager, type DocumentManagerConfig, DocumentMeta, type DocumentMetaInfo, E2EAbracadabraProvider, E2EEChannel, type E2EEIdentity, E2EOfflineStore, type EditMessageInput, EffectivePermissionEntry, EffectivePermissionsResponse, EffectiveRole, EncryptedChatClient, EncryptedYMap, EncryptedYText, type FetchInboxInput, type FetchNotificationsInput, FileBlobStore, FileTransferChannel, FileTransferHandle, type FileTransferMeta, type FileTransferStatus, type FoldedMessage, Forbidden, GEO_TYPE_META_SCHEMAS, type GetChatHistoryInput, HealthStatus, HocusPocusWebSocket, HocuspocusProvider, HocuspocusProviderConfiguration, HocuspocusProviderWebsocket, HocuspocusProviderWebsocketConfiguration, HocuspocusWebSocket, type IdentityDeviceEntry, type IdentityDocConfiguration, IdentityDocProvider, type IdentityProfile, type IdentityServerEntry, type IdentitySpaceEntry, type InboxEntry, type MarkReadInput$1 as InboxMarkReadInput, InviteRow, KEY_EXCHANGE_CHANNEL, Kind, ManualSignaling, type ManualSignalingBlob, type MessageRecord, MessageTooBig, MessageType, MetaFieldType, MetaManager, type NotificationReadUpdate, type NotificationRecord, NotificationsClient, OfflineStore, OutgoingMessageArguments, OutgoingMessageInterface, PAGE_TYPES, PageMeta, PageTypeInfo, PageTypeMetaField, type PairingRequest, type PairingResult, PeerConnection, type PeerInfo, type PeerState, PendingSubdoc, PermissionEntry, PublicKeyInfo, RPC_PREFIX, ReadyzStatus, ResetConnection, type RpcCallHandle, type RpcCallOptions, RpcClient, RpcError, type RpcErrorCode, type RpcErrorPayload, type RpcFrame, type RpcHandler, type RpcHandlerContext, type RpcKind, type RpcTarget, type RpcTransport, SERVER_ROOT_ID, SearchIndex, SearchResult, type SendChatMessageInput, type SendMessageInput, type SendMessageResult, ServerInfo, type SignalingIncoming, type SignalingOutgoing, SignalingSocket, SnapshotCreateResult, SnapshotData, SnapshotFileEntry, SnapshotForkResult, SnapshotMeta, SnapshotRestoreResult, StatesArray, SubdocMessage, SubdocRegisteredEvent, TYPE_ALIASES, TreeEntry, TreeManager, TreeNode, TreeSearchResult, Unauthorized, UploadInfo, UploadMeta, UploadQueueEntry, UploadQueueStatus, UserMetaField, UserProfile, WebSocketStatus, WsReadyStates, YjsDataChannel, attachUpdatedAtObserver, awarenessStatesToArray, wordlist as bip39Wordlist, buildBlockquoteElement, buildBlocksFromMarkdown, buildBulletListElement, buildCodeBlockElement, buildHeadingElement, buildHorizontalRuleElement, buildOrderedListElement, buildParagraphElement, buildTaskListElement, decryptChatContent, decryptField, deriveIdentityDocId, deriveSeedWrappingKey, encryptChatContent, encryptField, filenameToLabel, foldRecords, generateMnemonic, isEncryptedContent, makeEncryptedYMap, makeEncryptedYText, mnemonicToEd25519Seed, mnemonicToKeyPair, normalizeRootId, onAuthenticatedParameters, onAuthenticationFailedParameters, onAwarenessChangeParameters, onAwarenessUpdateParameters, onCloseParameters, onCompactedParameters, onDisconnectParameters, onMessageParameters, onOpenParameters, onOutgoingMessageParameters, onServerErrorParameters, onStatelessParameters, onStatusParameters, onSubdocLoadedParameters, onSubdocRegisteredParameters, onSyncedParameters, onUnsyncedChangesParameters, parseFrontmatter, populateYDocFromMarkdown, readAuthMessage, readBlocksFromFragment, recordFromYAny, resolvePageType, toPlain, unwrapSeed, validateMnemonic, waitForSync, withTimeout, wrapSeed, writeAuthenticated, writeAuthentication, writePermissionDenied, writeTokenSyncRequest, yjsToMarkdown };
4552
+ export { AbracadabraBaseProvider, AbracadabraBaseProviderConfiguration, AbracadabraClient, AbracadabraClientConfig, AbracadabraOutgoingMessageArguments, AbracadabraProvider, AbracadabraProviderConfiguration, AbracadabraWS, AbracadabraWSConfiguration, AbracadabraWebRTC, type AbracadabraWebRTCConfiguration, AbracadabraWebSocketConn, AdminConfigField, AdminConfigOriginKind, AuditLogEntry, AuditQueryOpts, AuditVerifyResult, AuthFailureContext, AuthFailureReason, AuthMessageType, AuthorizedScope, AwarenessError, BackgroundSyncManager, type BackgroundSyncManagerOptions, BackgroundSyncPersistence, BroadcastChannelSync, CHANNEL_NAMES, ChannelKeyResolver, type ChatChannel, ChatClient, type ChatClientTransport, type MarkReadInput as ChatMarkReadInput, type ChatMessage, type ChatReadCursor, type ChatReadReceipt, type ChatTypingEvent, CloseEvent, CompleteAbracadabraBaseProviderConfiguration, CompleteAbracadabraWSConfiguration, CompleteHocuspocusProviderConfiguration, CompleteHocuspocusProviderWebsocketConfiguration, ConnectionTimeout, Constructable, ConstructableOutgoingMessage, ContentManager, type CreateNotificationInput, CryptoIdentity, CryptoIdentityKeystore, DEFAULT_FILE_CHUNK_SIZE, DEFAULT_ICE_SERVERS, DataChannelRouter, type DeleteMessageInput, DevicePairingChannel, type DevicePairingConfig, DeviceRegistrationService, type DeviceServerStatus, type DeviceTier, type DocEncryptionInfo, DocKeyManager, DocSearchHit, type DocSyncState, type DocumentBlock, DocumentCache, type DocumentCacheOptions, type DocumentContent, DocumentManager, type DocumentManagerConfig, DocumentMeta, type DocumentMetaInfo, E2EAbracadabraProvider, E2EEChannel, type E2EEIdentity, E2EOfflineStore, type EditMessageInput, EffectivePermissionEntry, EffectivePermissionsResponse, EffectiveRole, EncryptedChatClient, EncryptedYMap, EncryptedYText, EnvSnapshotExtension, EnvSnapshotItem, EnvSnapshotResponse, type FetchInboxInput, type FetchNotificationsInput, FileBlobStore, FileTransferChannel, FileTransferHandle, type FileTransferMeta, type FileTransferStatus, type FoldedMessage, Forbidden, GEO_TYPE_META_SCHEMAS, type GetChatHistoryInput, HealthStatus, HocusPocusWebSocket, HocuspocusProvider, HocuspocusProviderConfiguration, HocuspocusProviderWebsocket, HocuspocusProviderWebsocketConfiguration, HocuspocusWebSocket, type IdentityDeviceEntry, type IdentityDocConfiguration, IdentityDocProvider, type IdentityProfile, type IdentityServerEntry, type IdentitySpaceEntry, type InboxEntry, type MarkReadInput$1 as InboxMarkReadInput, InviteRow, KEY_EXCHANGE_CHANNEL, Kind, ManualSignaling, type ManualSignalingBlob, type MessageRecord, MessageTooBig, MessageType, MetaFieldType, MetaManager, type NotificationReadUpdate, type NotificationRecord, NotificationsClient, OfflineStore, OutgoingMessageArguments, OutgoingMessageInterface, PAGE_TYPES, PageMeta, PageTypeInfo, PageTypeMetaField, type PairingRequest, type PairingResult, PeerConnection, type PeerInfo, type PeerState, PendingSubdoc, PermissionEntry, PublicKeyInfo, RPC_PREFIX, ReadyzStatus, ResetConnection, type RpcCallHandle, type RpcCallOptions, RpcClient, RpcError, type RpcErrorCode, type RpcErrorPayload, type RpcFrame, type RpcHandler, type RpcHandlerContext, type RpcKind, type RpcTarget, type RpcTransport, SERVER_ROOT_ID, SearchIndex, SearchResult, type SendChatMessageInput, type SendMessageInput, type SendMessageResult, ServerInfo, type SignalingIncoming, type SignalingOutgoing, SignalingSocket, SnapshotCreateResult, SnapshotData, SnapshotFileEntry, SnapshotForkResult, SnapshotMeta, SnapshotRestoreResult, StatesArray, SubdocMessage, SubdocRegisteredEvent, TYPE_ALIASES, TreeEntry, TreeManager, TreeNode, TreeSearchResult, Unauthorized, UploadInfo, UploadMeta, UploadQueueEntry, UploadQueueStatus, UserMetaField, UserProfile, WebSocketStatus, WsReadyStates, YjsDataChannel, attachUpdatedAtObserver, awarenessStatesToArray, wordlist as bip39Wordlist, buildBlockquoteElement, buildBlocksFromMarkdown, buildBulletListElement, buildCodeBlockElement, buildHeadingElement, buildHorizontalRuleElement, buildOrderedListElement, buildParagraphElement, buildTaskListElement, decryptChatContent, decryptField, deriveIdentityDocId, deriveSeedWrappingKey, encryptChatContent, encryptField, filenameToLabel, foldRecords, generateMnemonic, isEncryptedContent, makeEncryptedYMap, makeEncryptedYText, mnemonicToEd25519Seed, mnemonicToKeyPair, normalizeRootId, onAuthenticatedParameters, onAuthenticationFailedParameters, onAwarenessChangeParameters, onAwarenessUpdateParameters, onCloseParameters, onCompactedParameters, onDisconnectParameters, onMessageParameters, onOpenParameters, onOutgoingMessageParameters, onServerErrorParameters, onStatelessParameters, onStatusParameters, onSubdocLoadedParameters, onSubdocRegisteredParameters, onSyncedParameters, onUnsyncedChangesParameters, parseFrontmatter, populateYDocFromMarkdown, readAuthMessage, readBlocksFromFragment, recordFromYAny, resolvePageType, toPlain, unwrapSeed, validateMnemonic, waitForSync, withTimeout, wrapSeed, writeAuthenticated, writeAuthentication, writePermissionDenied, writeTokenSyncRequest, yjsToMarkdown };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abraca/dabra",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "abracadabra provider",
5
5
  "keywords": [
6
6
  "abracadabra",
@@ -611,6 +611,25 @@ export class AbracadabraBaseProvider extends EventEmitter {
611
611
  permissionDeniedHandler(reason: string) {
612
612
  this.emit("authenticationFailed", { reason });
613
613
  this.isAuthenticated = false;
614
+
615
+ // Stop the reconnect loop on a permanent denial. Without this the WS
616
+ // closes after every server-side rejection, AbracadabraWS schedules a
617
+ // retry, the new connection sends the same Subscribe → server denies
618
+ // again, ad infinitum (CPU/log/network spam, page looks "broken" to
619
+ // the user). The dominant cases:
620
+ // * "document not found" — entry-doc-id pinned to something that
621
+ // doesn't exist on this server
622
+ // * "permission denied" — operator never granted the user access
623
+ // Both are config issues; retrying won't fix them. We only stop the
624
+ // socket when this provider OWNS it (`manageSocket`); shared sockets
625
+ // (e.g. multiplexed child providers) leave the parent's lifecycle
626
+ // alone and just give up on this doc.
627
+ if (this.manageSocket) {
628
+ try {
629
+ this.configuration.websocketProvider.disconnect();
630
+ }
631
+ catch { /* WS may already be torn down — best effort */ }
632
+ }
614
633
  }
615
634
 
616
635
  authenticatedHandler(scope: string) {
@@ -19,6 +19,8 @@ import type {
19
19
  AuditLogEntry,
20
20
  AuditQueryOpts,
21
21
  AuditVerifyResult,
22
+ AdminConfigField,
23
+ EnvSnapshotResponse,
22
24
  } from "./types.ts";
23
25
  import { Kind, SERVER_ROOT_ID } from "./types.ts";
24
26
  import type { DocEncryptionInfo } from "./types.ts";
@@ -1103,6 +1105,60 @@ export class AbracadabraClient {
1103
1105
  return res.blob();
1104
1106
  }
1105
1107
 
1108
+ // ── Admin: runtime config store ──────────────────────────────────────────
1109
+
1110
+ /**
1111
+ * List every registered config field with current value + origin
1112
+ * (`default` / `env` / `global_override` / `route_override`). Requires
1113
+ * elevated role.
1114
+ */
1115
+ async adminConfigList(): Promise<AdminConfigField[]> {
1116
+ const res = await this.request<{ items: AdminConfigField[] }>(
1117
+ "GET", "/admin/config",
1118
+ );
1119
+ return res.items;
1120
+ }
1121
+
1122
+ /** Read a single config field by dotted path (e.g. `"access.authenticated"`). */
1123
+ async adminConfigGet(path: string): Promise<AdminConfigField> {
1124
+ return this.request<AdminConfigField>(
1125
+ "GET", `/admin/config/fields/${encodeURIComponent(path)}`,
1126
+ );
1127
+ }
1128
+
1129
+ /**
1130
+ * Set a runtime override on a config field. The field must be marked
1131
+ * `runtime_mutable = true` in the registry; immutable fields return a
1132
+ * schema error. Persists to the `settings_overrides` table.
1133
+ */
1134
+ async adminConfigSet(path: string, value: unknown): Promise<AdminConfigField> {
1135
+ return this.request<AdminConfigField>(
1136
+ "PUT", `/admin/config/fields/${encodeURIComponent(path)}`,
1137
+ { body: { value } },
1138
+ );
1139
+ }
1140
+
1141
+ /**
1142
+ * Clear a runtime override and revert the field to its env/TOML/default
1143
+ * base value. Returns `true` when an override was actually removed.
1144
+ */
1145
+ async adminConfigUnset(path: string): Promise<boolean> {
1146
+ const res = await this.request<{ existed: boolean }>(
1147
+ "DELETE", `/admin/config/fields/${encodeURIComponent(path)}`,
1148
+ );
1149
+ return res.existed;
1150
+ }
1151
+
1152
+ /**
1153
+ * Diagnostic dump of every `ABRA_*` env var the running process saw at
1154
+ * boot, mapped to its config path. Use this to debug
1155
+ * "I set this in `.env` but the server reports a different value".
1156
+ * Secrets are redacted (`value: null`, `redacted: true`).
1157
+ */
1158
+ async adminConfigEnvSnapshot(): Promise<EnvSnapshotResponse> {
1159
+ return this.request<EnvSnapshotResponse>("GET", "/admin/config/env-snapshot");
1160
+ }
1161
+
1106
1162
  // ── Snapshots ────────────────────────────────────────────────────────────
1107
1163
 
1108
1164
  /** List snapshot metadata for a document. */
package/src/types.ts CHANGED
@@ -456,6 +456,75 @@ export interface AuditVerifyResult {
456
456
  break?: { rows_checked: number; row_id: string; reason: string };
457
457
  }
458
458
 
459
+ // ── Admin: runtime config store ───────────────────────────────────────────────
460
+
461
+ /**
462
+ * Where the current value of a config field came from.
463
+ *
464
+ * * `default` — compiled-in default; nobody touched it.
465
+ * * `env` — set at startup by an `ABRA_*` env var.
466
+ * * `global_override` — admin runtime override via `/admin/config`.
467
+ * * `route_override` — per-route override (Phase 3).
468
+ */
469
+ export type AdminConfigOriginKind =
470
+ | "default"
471
+ | "env"
472
+ | "global_override"
473
+ | "route_override";
474
+
475
+ /** One entry returned by `GET /admin/config` and `GET /admin/config/fields/:path`. */
476
+ export interface AdminConfigField {
477
+ path: string;
478
+ section: string;
479
+ description: string;
480
+ env_var: string;
481
+ runtime_mutable: boolean;
482
+ value: unknown;
483
+ origin_kind: AdminConfigOriginKind;
484
+ /** Provenance — present only when origin_kind is a `*_override`. */
485
+ set_at?: number;
486
+ set_by?: string;
487
+ route?: string;
488
+ }
489
+
490
+ /**
491
+ * One row from `GET /admin/config/env-snapshot.items[]`. Reports whether
492
+ * each registry-known `ABRA_*` env var was set in the running process at
493
+ * boot, with secrets reported as `value: null` and `redacted: true`.
494
+ */
495
+ export interface EnvSnapshotItem {
496
+ env_var: string;
497
+ path: string;
498
+ section: string;
499
+ present: boolean;
500
+ /** Verbatim env value, or `null` for redacted (secrets) or unset. */
501
+ value: string | null;
502
+ redacted: boolean;
503
+ }
504
+
505
+ /**
506
+ * One row from `GET /admin/config/env-snapshot.extensions[]`. Extension
507
+ * overrides (`ABRA_EXT_<name>_<field>`) sit outside the registry and are
508
+ * reported by name with values inline.
509
+ */
510
+ export interface EnvSnapshotExtension {
511
+ env_var: string;
512
+ value: string;
513
+ }
514
+
515
+ /**
516
+ * `GET /admin/config/env-snapshot` response.
517
+ *
518
+ * `unknown` lists `ABRA_*` env vars present in the process that don't map
519
+ * to any registered field — i.e. typos. Operators that see their tweak
520
+ * land here instead of in `items` know they misspelled the var.
521
+ */
522
+ export interface EnvSnapshotResponse {
523
+ items: EnvSnapshotItem[];
524
+ extensions: EnvSnapshotExtension[];
525
+ unknown: string[];
526
+ }
527
+
459
528
  // ── Readiness ────────────────────────────────────────────────────────────────
460
529
 
461
530
  /** Response of `GET /readyz`. HTTP 200 when ready, 503 when not. */