@book.dev/sdk 1.60.0 → 1.64.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 (49) hide show
  1. package/dist/account.d.ts +11 -0
  2. package/dist/account.js +27 -0
  3. package/dist/account.js.map +1 -1
  4. package/dist/ai.d.ts +10 -0
  5. package/dist/ai.js +12 -0
  6. package/dist/ai.js.map +1 -1
  7. package/dist/authorize.d.ts +104 -0
  8. package/dist/authorize.js +151 -0
  9. package/dist/authorize.js.map +1 -0
  10. package/dist/authors.d.ts +26 -0
  11. package/dist/authors.js +81 -0
  12. package/dist/authors.js.map +1 -0
  13. package/dist/backup.d.ts +39 -0
  14. package/dist/backup.js +15 -0
  15. package/dist/backup.js.map +1 -1
  16. package/dist/client.d.ts +124 -3
  17. package/dist/client.js +106 -9
  18. package/dist/client.js.map +1 -1
  19. package/dist/connection.d.ts +23 -0
  20. package/dist/connection.js +56 -0
  21. package/dist/connection.js.map +1 -1
  22. package/dist/forwarding/index.d.ts +2 -1
  23. package/dist/forwarding/index.js +2 -1
  24. package/dist/forwarding/index.js.map +1 -1
  25. package/dist/forwarding/rosterAssertion.d.ts +49 -0
  26. package/dist/forwarding/rosterAssertion.js +89 -0
  27. package/dist/forwarding/rosterAssertion.js.map +1 -0
  28. package/dist/forwarding/tunnelClient.js +11 -1
  29. package/dist/forwarding/tunnelClient.js.map +1 -1
  30. package/dist/forwarding/tunnelProtocol.d.ts +11 -0
  31. package/dist/forwarding/tunnelProtocol.js +11 -0
  32. package/dist/forwarding/tunnelProtocol.js.map +1 -1
  33. package/dist/identity.d.ts +185 -0
  34. package/dist/identity.js +181 -0
  35. package/dist/identity.js.map +1 -0
  36. package/dist/index.d.ts +13 -9
  37. package/dist/index.js +9 -5
  38. package/dist/index.js.map +1 -1
  39. package/dist/provenance.d.ts +155 -0
  40. package/dist/provenance.js +23 -0
  41. package/dist/provenance.js.map +1 -0
  42. package/dist/routes.d.ts +53 -0
  43. package/dist/routes.js +50 -0
  44. package/dist/routes.js.map +1 -1
  45. package/dist/suggestions.d.ts +17 -2
  46. package/dist/types.d.ts +91 -0
  47. package/dist/types.js +9 -0
  48. package/dist/types.js.map +1 -1
  49. package/package.json +6 -1
package/dist/index.js CHANGED
@@ -1,19 +1,23 @@
1
- export { emptyPageSnapshot } from './types';
1
+ export { emptyPageSnapshot, PAGE_VISIBILITIES } from './types';
2
2
  export { API } from './routes';
3
3
  export { HttpDataClient } from './client';
4
- export { ForwardingClient, TunnelClient, MemoryKeyStore, mintSiteKeypair, signWithSiteKey, } from './forwarding';
4
+ export { ForwardingClient, TunnelClient, MemoryKeyStore, mintSiteKeypair, signWithSiteKey, verifyWithSiteKey, FORWARDED_HEADER, signRosterAssertion, verifyRosterAssertion, ROSTER_ASSERTION_VERSION, ROSTER_ASSERTION_SKEW_MS, } from './forwarding';
5
5
  export { TITLE_PROPERTY_ID, SELECT_COLORS, NO_VALUE_GROUP, STATUS_GROUPS, RELATIVE_DATE_OPS, projectExports, rowValue, matchesFilter, rowMatchesCondition, applyView, viewFilterRoot, isFilterGroup, shortId, defaultDatabaseSchema, defaultView, defaultStatusOptions, removeProperty, formatNumber, formatUniqueId, numberProgress, groupRows, groupRowsBy, groupRowsByParent, PARENT_GROUP_ID, NO_PARENT_GROUP, aggregateRows, aggregateMatrix, CHART_TOTAL_SERIES, summarizeColumn, dateStart, dateEnd, parseDay, rowDateSpan, rowLocation, asLocation, dependencyGraph, syncInverseUpdates, relationSides, buildRowTree, flattenRowTree, isImageUrl, firstImageUrl, coverImageUrl, } from './database';
6
6
  export { evaluateFormula, formulaReferences, FormulaError, } from './formula';
7
7
  export { OWNER_PROPERTY_ID, VERIFICATION_PROPERTY_ID, BACKLINKS_PROPERTY_ID, THEME_PROPERTY_ID, COVER_PROPERTY_ID, FONTS_PROPERTY_ID, ICON_PROPERTY_ID, FULLWIDTH_PROPERTY_ID, SYSTEM_PAGE_PROPERTIES, isVerified, verificationExpired, isVerificationActive, makeVerification, extractMentionIds, propertiesReferencePage, } from './pageProperties';
8
- export { getServerUrlOverride, setServerUrlOverride, getServerTokenOverride, setServerTokenOverride, isMixedContentBlocked } from './connection';
8
+ export { getServerUrlOverride, setServerUrlOverride, getServerTokenOverride, setServerTokenOverride, getIdentityCredential, setIdentityToken, setGuestName, getForwardingAudience, setForwardingAudience, isMixedContentBlocked } from './connection';
9
9
  export { AccountClient, AccountError, DEFAULT_ACCOUNT_URL, getAccountUrlOverride, setAccountUrlOverride, resolveAccountUrl, } from './account';
10
+ export { guestPrincipal, localPrincipal, principalId, mintIdentityKeypair, signIdentity, decodeIdentity, verifyIdentity, principalFromClaims, unverifiedPrincipalFromClaims, } from './identity';
11
+ export { DEFAULT_INSTANCE_CONFIG, } from './provenance';
12
+ export { authorize, isEmailAuthoritative, } from './authorize';
10
13
  export { snapshotText, paragraphBlocks, textSnapshot, appendTextToSnapshot, appendBlocksToSnapshot } from './content';
11
14
  export { snapshotBlocks, contentHash, computeBlockMtimes, stampSnapshotMtimes, latestBlockMtime, } from './mtime';
15
+ export { computeBlockAuthors, stampSnapshotAuthors, latestSnapshotAuthor } from './authors';
12
16
  export { pageToBookHtml, bookHtmlToPage, readBookHtmlMeta, slugify, } from './bookfile';
13
17
  export { spaceToBookFiles, parseBookFolder, SPACE_BUNDLE_FILE, } from './bookFolder';
14
18
  export { canonicalDigest, generateRegistryKeys, signPlugin, verifyPlugin, validateManifest, OPENBOOK_REGISTRY, } from './plugins';
15
19
  export { buildSampleDocument, seedSampleDocument, SAMPLE_DOCUMENT_NAME } from './sampleDocument';
16
20
  export { PAGE_TEMPLATES, instantiateTemplate } from './templates';
17
- export { BACKUP_VERSION, remapBundle, } from './backup';
18
- export { providerSettings } from './ai';
21
+ export { BACKUP_VERSION, BACKUP_CADENCES, BACKUP_CADENCE_MS, DEFAULT_BACKUP_CONFIG, remapBundle, } from './backup';
22
+ export { providerSettings, isPaidProvider } from './ai';
19
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,iBAAiB,EAAC,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAC,GAAG,EAAgB,MAAM,UAAU,CAAC;AAE5C,OAAO,EAAC,cAAc,EAAC,MAAM,UAAU,CAAC;AACxC,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,eAAe,GAKhB,MAAM,cAAc,CAAC;AAgDtB,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,aAAa,EACb,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,aAAa,EACb,OAAO,EACP,qBAAqB,EACrB,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,cAAc,EACd,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,OAAO,EACP,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,UAAU,EACV,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,YAAY,GAGb,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,GAExB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,qBAAqB,EAAC,MAAM,cAAc,CAAC;AAC/I,OAAO,EACL,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,GAElB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,oBAAoB,EAAE,sBAAsB,EAAmB,MAAM,WAAW,CAAC;AACtI,OAAO,EACL,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GAEjB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,OAAO,GAER,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAGlB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,GAMlB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,mBAAmB,EAAE,kBAAkB,EAAE,oBAAoB,EAAC,MAAM,kBAAkB,CAAC;AAa/F,OAAO,EAAC,cAAc,EAAE,mBAAmB,EAAoB,MAAM,aAAa,CAAC;AACnF,OAAO,EACL,cAAc,EACd,WAAW,GAKZ,MAAM,UAAU,CAAC;AAkBlB,OAAO,EAAC,gBAAgB,EAAC,MAAM,MAAM,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Multi-user instance policy + change provenance (OB-165). The contract the
3
+ * server and clients share for: the guest-access gate, the set of trusted
4
+ * identity issuers, and the durable per-change edit log.
5
+ *
6
+ * Design: `docs/multi-user-and-backups-2026-06.md`.
7
+ */
8
+ import type { Jwks, Principal, VerifiedVia } from './identity';
9
+ import type { MemberRole, PageVisibility } from './types';
10
+ /** What an unauthenticated (guest) caller may do on this instance. */
11
+ export type GuestAccess =
12
+ /** Guests are rejected entirely (sign-in required). */
13
+ 'off'
14
+ /** Guests may read, but not write. */
15
+ | 'read'
16
+ /** Guests may read and write (the default — same as a no-login workspace today). */
17
+ | 'write';
18
+ /** An identity issuer this instance trusts (issuer-rooted federation). */
19
+ export interface TrustedIssuerConfig {
20
+ /** The `iss` claim this config authorizes. */
21
+ issuer: string;
22
+ /** Where to (re)fetch the issuer's JWKS for online refresh. */
23
+ jwksUrl?: string;
24
+ /** Inline / cached JWKS — makes verification offline-capable (and is how the
25
+ * dev issuer ships its key). */
26
+ jwks?: Jwks;
27
+ }
28
+ /** The instance's multi-user policy, persisted in the `settings` table. */
29
+ export interface InstanceConfig {
30
+ guestAccess: GuestAccess;
31
+ /** The principal subject that administers this instance, once claimed. */
32
+ ownerSubject?: string;
33
+ trustedIssuers: TrustedIssuerConfig[];
34
+ /**
35
+ * This server's own audience identifier (OB-177). When set, an identity token
36
+ * scoped to a *different* audience is rejected, and clients should request a
37
+ * token bound to this value. Leave unset for the single-server model.
38
+ */
39
+ audience?: string;
40
+ /** Require every identity token to be audience-bound to {@link audience}
41
+ * (reject unscoped tokens). Multi-server hardening. */
42
+ requireAudience?: boolean;
43
+ /**
44
+ * Default audience scope a page's `visibility='inherit'` resolves to at the root
45
+ * (OB-182 §2.4, Fork 1). Set to `'members'` (private) when the instance is
46
+ * claimed; an unclaimed instance never reaches the access path. Never `'inherit'`.
47
+ */
48
+ defaultVisibility?: Exclude<PageVisibility, 'inherit'>;
49
+ /**
50
+ * The ONE issuer whose `email` claim is trusted for persona / email-ACL matching
51
+ * (OB-182 §2.4, B1). Subject-based grants work for any {@link trustedIssuers}
52
+ * entry, but only a token from `emailAuthority` can satisfy an email persona or
53
+ * an email ACL. Must be one of {@link trustedIssuers} or every email grant
54
+ * silently (and safely) stops matching. Defaults to account.book.pub.
55
+ */
56
+ emailAuthority?: string;
57
+ /**
58
+ * When this instance is a MANAGED workspace (OB-199), the account workspace it
59
+ * is bound to. Set, the periodic roster sync projects that workspace's roster
60
+ * (admins / viewers + the workspace owner) into the local `members` table so
61
+ * `members`-scope + admin/viewer roles resolve for direct (non-edge) access too.
62
+ * Unset ⇒ a standalone instance; the sync is inert. Additive — absence is the
63
+ * pre-OB-199 single-instance behaviour. Holds non-secret COORDINATES only; the
64
+ * credential the instance presents to read the roster is supplied out-of-band
65
+ * (never persisted in policy). See {@link WorkspaceBinding}.
66
+ */
67
+ workspaceBinding?: WorkspaceBinding;
68
+ }
69
+ /**
70
+ * Binds a managed instance to an account workspace (OB-199). Non-secret
71
+ * coordinates only — the roster-read credential is injected at runtime, never
72
+ * stored here. Set by the owner (via the instance-policy route) or learned during
73
+ * the forwarding/claim flow.
74
+ */
75
+ export interface WorkspaceBinding {
76
+ /** The account workspace id this instance serves. */
77
+ workspaceId: string;
78
+ /**
79
+ * Base URL of the account that owns the workspace (where the roster lives).
80
+ * Defaults to the instance `emailAuthority` (account.book.pub) when omitted.
81
+ */
82
+ accountBaseUrl?: string;
83
+ }
84
+ /**
85
+ * One entry of the account workspace roster (OB-197 contract), as consumed by the
86
+ * OB-199 sync. Identifies a member by a bound `subject` (`iss#sub`) and/or a
87
+ * persona `email`, with the workspace role. The account is the producer; the
88
+ * instance only reads this shape (it never writes the account).
89
+ */
90
+ export interface WorkspaceRosterEntry {
91
+ /** Bound `iss#sub` of the member, when the account exposes it. */
92
+ subject?: string;
93
+ /** Persona email (any case; lowercased on sync). */
94
+ email?: string;
95
+ role: MemberRole;
96
+ }
97
+ /**
98
+ * The account workspace roster returned by `GET /api/workspaces/:id/members`
99
+ * (OB-197), as consumed by the OB-199 sync. `ownerSubject` is the workspace
100
+ * owner's bound subject (`iss#sub`) — admitted as an admin even when it differs
101
+ * from the instance's own site owner (OB-198 F2), so the workspace owner is never
102
+ * locked out of a workspace they own.
103
+ */
104
+ export interface WorkspaceRoster {
105
+ workspaceId: string;
106
+ /** Bound `iss#sub` of the workspace owner (admitted as admin). */
107
+ ownerSubject?: string;
108
+ members: WorkspaceRosterEntry[];
109
+ }
110
+ export declare const DEFAULT_INSTANCE_CONFIG: InstanceConfig;
111
+ /**
112
+ * Public view of the instance policy returned by `GET /api/instance` — issuer
113
+ * URLs only (never private JWKS material), plus the principal resolved for the
114
+ * *current* request, so a client can render "you are signed in as …" / "guest".
115
+ */
116
+ export interface InstanceInfo {
117
+ guestAccess: GuestAccess;
118
+ ownerSubject: string | null;
119
+ trustedIssuers: string[];
120
+ /** This server's audience identifier, so a client can request an `aud`-scoped
121
+ * identity token (OB-177). `null` for the single-server (unscoped) model. */
122
+ audience: string | null;
123
+ /** Whether this instance *requires* every identity token to be bound to
124
+ * {@link audience} (OB-202). Lets a client short-circuit the audience-bind on
125
+ * relaunch: when the server already persisted `audience==host && requireAudience`
126
+ * it only needs to ensure its own token is scoped, never to relax + re-assert.
127
+ * Optional: absent (e.g. a pre-OB-202 server / a test fixture) is treated as `false`. */
128
+ requireAudience?: boolean;
129
+ /** Who the server resolved you to be on this request. */
130
+ you: Principal;
131
+ /**
132
+ * Your active-persona roster role on this request (OB-182 §1.1), or `null` if
133
+ * you aren't an active member. Lets a client gate manager-only UI (the per-page
134
+ * Share dialog) without a per-page probe: `admin` (and the owner / loopback,
135
+ * derivable from {@link you} + {@link ownerSubject}) manage sharing.
136
+ * Optional: absent (a pre-OB-203 server / a test fixture) is treated as `null`.
137
+ */
138
+ youRole?: MemberRole | null;
139
+ }
140
+ /** One recorded change — a row of the append-only edit log. */
141
+ export interface StoredEdit {
142
+ id: string;
143
+ pageId: string | null;
144
+ authorSubject: string;
145
+ authorIssuer: string;
146
+ authorName: string;
147
+ verifiedVia: VerifiedVia;
148
+ /** What kind of change: `page.save`, `page.create`, `page.delete`, `row.update`, … */
149
+ kind: string;
150
+ /** The signed credential that authorized it (users only). */
151
+ assertionKid: string | null;
152
+ assertionJti: string | null;
153
+ summary: string;
154
+ createdAt: string;
155
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Multi-user instance policy + change provenance (OB-165). The contract the
3
+ * server and clients share for: the guest-access gate, the set of trusted
4
+ * identity issuers, and the durable per-change edit log.
5
+ *
6
+ * Design: `docs/multi-user-and-backups-2026-06.md`.
7
+ */
8
+ import { DEFAULT_ACCOUNT_URL } from './account';
9
+ export const DEFAULT_INSTANCE_CONFIG = {
10
+ guestAccess: 'write',
11
+ // Trust account.book.pub out of the box — it's the OpenBook identity authority
12
+ // (the shared root that makes identities federate across instances). Only ever
13
+ // consulted when an `iss=account.book.pub` assertion is actually presented; the
14
+ // JWKS is fetched + cached lazily. Override or extend in instance settings.
15
+ trustedIssuers: [{ issuer: DEFAULT_ACCOUNT_URL, jwksUrl: `${DEFAULT_ACCOUNT_URL}/api/identity/jwks` }],
16
+ // `inherit` at the root resolves here. Private-by-default once claimed (Fork 1);
17
+ // an unclaimed instance short-circuits before this is ever consulted (rule 0).
18
+ defaultVisibility: 'members',
19
+ // account.book.pub is the default email-authority — the one issuer whose `email`
20
+ // claim drives persona / email-ACL matching (B1). It is already trusted above.
21
+ emailAuthority: DEFAULT_ACCOUNT_URL,
22
+ };
23
+ //# sourceMappingURL=provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provenance.js","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAC,mBAAmB,EAAC,MAAM,WAAW,CAAC;AA8G9C,MAAM,CAAC,MAAM,uBAAuB,GAAmB;IACrD,WAAW,EAAE,OAAO;IACpB,+EAA+E;IAC/E,+EAA+E;IAC/E,gFAAgF;IAChF,4EAA4E;IAC5E,cAAc,EAAE,CAAC,EAAC,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,GAAG,mBAAmB,oBAAoB,EAAC,CAAC;IACpG,iFAAiF;IACjF,+EAA+E;IAC/E,iBAAiB,EAAE,SAAS;IAC5B,iFAAiF;IACjF,+EAA+E;IAC/E,cAAc,EAAE,mBAAmB;CACpC,CAAC"}
package/dist/routes.d.ts CHANGED
@@ -82,7 +82,60 @@ export declare const API: {
82
82
  readonly comments: (pageId: string) => string;
83
83
  /** A single comment: `DELETE`. */
84
84
  readonly comment: (id: string) => string;
85
+ /**
86
+ * On-demand heavy database compaction (`POST`): VACUUM FULL to physically
87
+ * reclaim heap bloat. Embedded (PGlite) only — a server backed by external
88
+ * Postgres answers 409. See OB-164.
89
+ */
90
+ readonly compact: "/api/maintenance/compact";
91
+ /**
92
+ * Instance multi-user policy: `GET` returns {@link InstanceInfo} (guest
93
+ * policy, trusted issuer URLs, and the principal resolved for *this* request);
94
+ * `PUT` updates the policy (owner only).
95
+ */
96
+ readonly instance: "/api/instance";
97
+ /** A page's change provenance (the edit log), newest first: `GET`. */
98
+ readonly pageEdits: (id: string) => string;
99
+ /**
100
+ * The member roster: `GET` (list) / `POST` (invite by email or handle/subject).
101
+ * Instance-writer (owner/admin/loopback) only — managing or even seeing the
102
+ * roster is a privileged action.
103
+ */
104
+ readonly members: "/api/members";
105
+ /** A single roster row: `PATCH` (role/status) / `DELETE` (revoke). */
106
+ readonly member: (id: string) => string;
107
+ /**
108
+ * A page's per-page ACL grants: `GET` (list) / `POST` (share to an email or
109
+ * handle/subject) / `DELETE` (`?subject=` | `?email=` to revoke). Gated on
110
+ * write of the page itself (you manage sharing of pages you can write).
111
+ */
112
+ readonly pageAcl: (id: string) => string;
113
+ /**
114
+ * A page's audience-scope visibility (OB-182 §1.1): `GET` returns
115
+ * `{visibility}` (read-gated); `PUT` `{visibility}` sets it (write-gated — same
116
+ * "you manage sharing of pages you can write" rule as the ACL).
117
+ */
118
+ readonly pageVisibility: (id: string) => string;
119
+ /**
120
+ * On-demand roster sync of a managed instance: `GET` reports the binding +
121
+ * last-sync status; `POST` pulls the bound workspace roster from the account and
122
+ * reconciles it into the local roster (managed rows only). Instance-writer
123
+ * (owner/admin/loopback) only. The same sync also runs periodically.
124
+ */
125
+ readonly workspaceSync: "/api/workspace/sync";
126
+ /** Scheduled-backup policy: `GET` returns {@link BackupStatus}; `PUT` updates
127
+ * the policy and returns the new status. */
128
+ readonly backups: "/api/backups";
129
+ /** Run a backup immediately: `POST` `{cadence?}` → the written file's name. */
130
+ readonly backupRun: "/api/backups/run";
85
131
  };
132
+ /** Result of a {@link API.compact} run: the database's on-disk size before/after,
133
+ * in bytes, and how much was reclaimed. */
134
+ export interface CompactResult {
135
+ before: number;
136
+ after: number;
137
+ reclaimed: number;
138
+ }
86
139
  /** Error body shape returned by the API for non-2xx responses. */
87
140
  export interface ApiError {
88
141
  error: string;
package/dist/routes.js CHANGED
@@ -85,5 +85,55 @@ export const API = {
85
85
  comments: (pageId) => `/api/pages/${encodeURIComponent(pageId)}/comments`,
86
86
  /** A single comment: `DELETE`. */
87
87
  comment: (id) => `/api/comments/${encodeURIComponent(id)}`,
88
+ /**
89
+ * On-demand heavy database compaction (`POST`): VACUUM FULL to physically
90
+ * reclaim heap bloat. Embedded (PGlite) only — a server backed by external
91
+ * Postgres answers 409. See OB-164.
92
+ */
93
+ compact: '/api/maintenance/compact',
94
+ // ── Multi-user (identity, policy, provenance) — OB-165 ───────────────────────
95
+ /**
96
+ * Instance multi-user policy: `GET` returns {@link InstanceInfo} (guest
97
+ * policy, trusted issuer URLs, and the principal resolved for *this* request);
98
+ * `PUT` updates the policy (owner only).
99
+ */
100
+ instance: '/api/instance',
101
+ /** A page's change provenance (the edit log), newest first: `GET`. */
102
+ pageEdits: (id) => `/api/pages/${encodeURIComponent(id)}/edits`,
103
+ // ── Sharing: roster invites + per-page ACL — OB-191 ──────────────────────────
104
+ /**
105
+ * The member roster: `GET` (list) / `POST` (invite by email or handle/subject).
106
+ * Instance-writer (owner/admin/loopback) only — managing or even seeing the
107
+ * roster is a privileged action.
108
+ */
109
+ members: '/api/members',
110
+ /** A single roster row: `PATCH` (role/status) / `DELETE` (revoke). */
111
+ member: (id) => `/api/members/${encodeURIComponent(id)}`,
112
+ /**
113
+ * A page's per-page ACL grants: `GET` (list) / `POST` (share to an email or
114
+ * handle/subject) / `DELETE` (`?subject=` | `?email=` to revoke). Gated on
115
+ * write of the page itself (you manage sharing of pages you can write).
116
+ */
117
+ pageAcl: (id) => `/api/pages/${encodeURIComponent(id)}/acl`,
118
+ /**
119
+ * A page's audience-scope visibility (OB-182 §1.1): `GET` returns
120
+ * `{visibility}` (read-gated); `PUT` `{visibility}` sets it (write-gated — same
121
+ * "you manage sharing of pages you can write" rule as the ACL).
122
+ */
123
+ pageVisibility: (id) => `/api/pages/${encodeURIComponent(id)}/visibility`,
124
+ // ── Managed workspace: instance ↔ workspace roster sync — OB-199 ─────────────
125
+ /**
126
+ * On-demand roster sync of a managed instance: `GET` reports the binding +
127
+ * last-sync status; `POST` pulls the bound workspace roster from the account and
128
+ * reconciles it into the local roster (managed rows only). Instance-writer
129
+ * (owner/admin/loopback) only. The same sync also runs periodically.
130
+ */
131
+ workspaceSync: '/api/workspace/sync',
132
+ // ── Scheduled backups — OB-166 ───────────────────────────────────────────────
133
+ /** Scheduled-backup policy: `GET` returns {@link BackupStatus}; `PUT` updates
134
+ * the policy and returns the new status. */
135
+ backups: '/api/backups',
136
+ /** Run a backup immediately: `POST` `{cadence?}` → the written file's name. */
137
+ backupRun: '/api/backups/run',
88
138
  };
89
139
  //# sourceMappingURL=routes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,MAAM,EAAE,SAAS;IACjB,kDAAkD;IAClD,KAAK,EAAE,YAAY;IACnB,oFAAoF;IACpF,IAAI,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE;IACpE,wFAAwF;IACxF,cAAc,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,aAAa;IACzF,+DAA+D;IAC/D,aAAa,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,YAAY;IACvF,wEAAwE;IACxE,WAAW,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,UAAU;IACnF,qFAAqF;IACrF,QAAQ,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,OAAO;IAC7E,kFAAkF;IAClF,WAAW,EAAE,aAAa;IAC1B,4EAA4E;IAC5E,WAAW,EAAE,aAAa;IAC1B,gFAAgF;IAChF,KAAK,EAAE,YAAY;IACnB,8EAA8E;IAC9E,SAAS,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE;IACzE,iEAAiE;IACjE,MAAM,EAAE,aAAa;IACrB,6DAA6D;IAC7D,UAAU,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,SAAS;IACjF;;;;;OAKG;IACH,IAAI,EAAE,WAAW;IAEjB,8EAA8E;IAC9E,8DAA8D;IAC9D,SAAS,EAAE,gBAAgB;IAC3B,mEAAmE;IACnE,QAAQ,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,kBAAkB,kBAAkB,CAAC,EAAE,CAAC,EAAE;IAC5E,4EAA4E;IAC5E,YAAY,EAAE,CAAC,MAAc,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,MAAM,CAAC,WAAW;IAC7F,oEAAoE;IACpE,YAAY,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,kBAAkB,kBAAkB,CAAC,EAAE,CAAC,OAAO;IACrF,sDAAsD;IACtD,iBAAiB,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,kBAAkB,kBAAkB,CAAC,EAAE,CAAC,aAAa;IAChG,mGAAmG;IACnG,WAAW,EAAE,CAAC,EAAU,EAAE,KAAa,EAAU,EAAE,CACjD,kBAAkB,kBAAkB,CAAC,EAAE,CAAC,SAAS,kBAAkB,CAAC,KAAK,CAAC,EAAE;IAC9E,gFAAgF;IAChF,cAAc,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,kBAAkB,kBAAkB,CAAC,EAAE,CAAC,SAAS;IAEzF,8EAA8E;IAC9E,kFAAkF;IAClF,QAAQ,EAAE,gBAAgB;IAC1B,8EAA8E;IAC9E,QAAQ,EAAE,gBAAgB;IAC1B,+CAA+C;IAC/C,OAAO,EAAE,eAAe;IACxB,0EAA0E;IAC1E,QAAQ,EAAE,gBAAgB;IAC1B,yEAAyE;IACzE,UAAU,EAAE,kBAAkB;IAC9B,qEAAqE;IACrE,OAAO,EAAE,eAAe;IACxB,4EAA4E;IAC5E,UAAU,EAAE,kBAAkB;IAC9B,wEAAwE;IACxE,eAAe,EAAE,yBAAyB;IAC1C,sHAAsH;IACtH,SAAS,EAAE,iBAAiB;IAC5B,mFAAmF;IACnF,QAAQ,EAAE,gBAAgB;IAC1B,mCAAmC;IACnC,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,kBAAkB,kBAAkB,CAAC,IAAI,CAAC,EAAE;IACvE,OAAO,EAAE,cAAc;IACvB,MAAM,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,gBAAgB,EAAE,EAAE;IAE5C,gFAAgF;IAChF,uFAAuF;IACvF,WAAW,EAAE,CAAC,MAAc,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,MAAM,CAAC,cAAc;IAC/F,2EAA2E;IAC3E,UAAU,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,oBAAoB,kBAAkB,CAAC,EAAE,CAAC,EAAE;IAChF,mGAAmG;IACnG,QAAQ,EAAE,CAAC,MAAc,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,MAAM,CAAC,WAAW;IACzF,kCAAkC;IAClC,OAAO,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,iBAAiB,kBAAkB,CAAC,EAAE,CAAC,EAAE;IAE1E;;;;OAIG;IACH,OAAO,EAAE,0BAA0B;IAEnC,gFAAgF;IAChF;;;;OAIG;IACH,QAAQ,EAAE,eAAe;IACzB,sEAAsE;IACtE,SAAS,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,QAAQ;IAE/E,gFAAgF;IAChF;;;;OAIG;IACH,OAAO,EAAE,cAAc;IACvB,sEAAsE;IACtE,MAAM,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE;IACxE;;;;OAIG;IACH,OAAO,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,MAAM;IAC3E;;;;OAIG;IACH,cAAc,EAAE,CAAC,EAAU,EAAU,EAAE,CAAC,cAAc,kBAAkB,CAAC,EAAE,CAAC,aAAa;IAEzF,gFAAgF;IAChF;;;;;OAKG;IACH,aAAa,EAAE,qBAAqB;IAEpC,gFAAgF;IAChF;iDAC6C;IAC7C,OAAO,EAAE,cAAc;IACvB,+EAA+E;IAC/E,SAAS,EAAE,kBAAkB;CACrB,CAAC"}
@@ -34,8 +34,23 @@ export interface CommentRun {
34
34
  a?: string;
35
35
  };
36
36
  }
37
+ import type { VerifiedVia } from './identity';
37
38
  /** Who authored a suggestion or comment. */
38
39
  export type SuggestionAuthorKind = 'ai' | 'human';
40
+ /**
41
+ * Server-stamped author identity (OB-165) carried alongside the display
42
+ * `authorName`. Unlike `authorName` (a label the client supplies), these come
43
+ * from the request's *verified* principal, so they're the authoritative "who".
44
+ * Absent on rows written before multi-user, or by an unauthenticated path.
45
+ */
46
+ export interface AuthoredIdentity {
47
+ /** The principal's stable subject (`iss#sub`, or `guest:<name>`). */
48
+ authorSubject?: string;
49
+ /** The issuer that vouched for a verified author (empty for guests). */
50
+ authorIssuer?: string;
51
+ /** How the author was established (`jws` / `guest` / `unverified` / `local`). */
52
+ authorVerified?: VerifiedVia;
53
+ }
39
54
  /** The change a suggestion proposes — mirrors the agent write-tool kinds. */
40
55
  export type SuggestionKind = 'replace-text' | 'set-cell' | 'insert' | 'delete' | 'set-theme';
41
56
  /** Lifecycle of a suggestion. */
@@ -60,7 +75,7 @@ export interface SuggestionTarget {
60
75
  propertyId?: string;
61
76
  }
62
77
  /** A persisted, reviewable proposed change to a page. */
63
- export interface StoredSuggestion {
78
+ export interface StoredSuggestion extends AuthoredIdentity {
64
79
  id: string;
65
80
  pageId: string;
66
81
  authorKind: SuggestionAuthorKind;
@@ -100,7 +115,7 @@ export interface SuggestionUpdate {
100
115
  status?: SuggestionStatus;
101
116
  }
102
117
  /** A threaded comment on a suggestion, or a standalone comment on a block. */
103
- export interface StoredComment {
118
+ export interface StoredComment extends AuthoredIdentity {
104
119
  id: string;
105
120
  pageId: string;
106
121
  /** The suggestion this comment belongs to (a review-thread comment). */
package/dist/types.d.ts CHANGED
@@ -31,6 +31,15 @@ export interface PageSnapshot {
31
31
  * written before the feature shipped (treated as "unknown — assume changed").
32
32
  */
33
33
  mtimes?: Array<[string, string]>;
34
+ /**
35
+ * `[blockId, subject]` pairs — the *verified* author (`iss#sub`) who last
36
+ * changed each block, a sparse map carried with the snapshot so an edit is
37
+ * still correctly attributed after it syncs to another instance (OB-170). The
38
+ * server stamps it on write from the request's verified principal; only
39
+ * verified identities appear (guest/local/unverified edits are not recorded
40
+ * here). Absent on single-user / unverified documents. See sdk `authors.ts`.
41
+ */
42
+ authors?: Array<[string, string]>;
34
43
  }
35
44
  /** An empty snapshot, for initializing a brand-new page. */
36
45
  export declare const emptyPageSnapshot: () => PageSnapshot;
@@ -96,6 +105,88 @@ export interface PageInput {
96
105
  */
97
106
  parentId?: string | null;
98
107
  }
108
+ /**
109
+ * Sharing & access model (OB-188; contract docs/sharing-access-contract-spike-OB-182.md).
110
+ * These are the data-model types behind migration 0011 — the roster row, the
111
+ * per-page ACL row, and the per-page visibility scope. The *authorization* layer
112
+ * (`authorize()` in §1.1) is OB-189 and is intentionally NOT defined here.
113
+ */
114
+ /**
115
+ * Per-page audience scope (OB-182 §1.1). `inherit` resolves up the **parent**
116
+ * chain for an ordinary page (or, for a database row, via the database host page)
117
+ * down to `InstanceConfig.defaultVisibility` at the root. The other four are the
118
+ * fixed audience scopes: `public` (anyone, incl. anonymous), `authenticated` (any
119
+ * signed-in jws user), `members` (active roster members), `restricted`
120
+ * (owner/admin/ACL only).
121
+ */
122
+ export type PageVisibility = 'inherit' | 'public' | 'authenticated' | 'members' | 'restricted';
123
+ /** Alias for {@link PageVisibility} (the OB-188 directive's shorthand name). */
124
+ export type Visibility = PageVisibility;
125
+ /** Every {@link PageVisibility} value, in escalating-privacy order — the source of
126
+ * truth for server-side validation and the share dialog's scope picker. */
127
+ export declare const PAGE_VISIBILITIES: readonly PageVisibility[];
128
+ /** The two OSS roster roles (OB-182): `admin` = full access, `viewer` = locked
129
+ * read-only. (Contract §1.1 names this union `Role`.) */
130
+ export type MemberRole = 'admin' | 'viewer';
131
+ /**
132
+ * Lifecycle of a roster row (OB-182 §2.1). `invited` = an email persona not yet
133
+ * claimed by a signed-in subject; `active` = bound + live; `suspended` = retained
134
+ * but grants nothing. Only `active` rows resolve to a role at request time (S3).
135
+ */
136
+ export type MemberStatus = 'invited' | 'active' | 'suspended';
137
+ /**
138
+ * Where a roster row came from (OB-199). `local` = a locally-issued invite (the
139
+ * OB-191 path); `managed` = projected from the bound account workspace's roster by
140
+ * the periodic sync. The two coexist: the managed sync only ever touches `managed`
141
+ * rows, so a local invite is never clobbered (and vice-versa).
142
+ */
143
+ export type MemberSource = 'local' | 'managed';
144
+ /** Per-page ACL grant level (OB-182 §1.1). */
145
+ export type AclLevel = 'read' | 'write';
146
+ /**
147
+ * One roster row — the data-server-native `members` table (OB-182 §2.1). A row is
148
+ * either an EMAIL PERSONA (`email` set, `subject` NULL until claimed on sign-in)
149
+ * or a SUBJECT/handle MEMBER (`subject` set, `email` NULL). One account `subject`
150
+ * may back several persona rows — one per verified email — each its own member
151
+ * with its own role. `issuer` PINS the email-authority for a persona so a federated
152
+ * issuer can never satisfy an `account.book.pub`-scoped grant (B1).
153
+ */
154
+ export interface Member {
155
+ id: string;
156
+ /** Bound `iss#sub`; `null` until an email persona is claimed. */
157
+ subject: string | null;
158
+ /** Persona email (lowercased); `null` for a subject/handle member. */
159
+ email: string | null;
160
+ /** The pinned email-authority issuer for a persona (B1). */
161
+ issuer: string;
162
+ role: MemberRole;
163
+ status: MemberStatus;
164
+ /**
165
+ * Provenance of the row (OB-199): `local` for a locally-issued invite (OB-191),
166
+ * `managed` for a row projected from the bound workspace roster. Defaults to
167
+ * `local`; the managed sync only ever writes/removes `managed` rows.
168
+ * Optional: absent (a pre-OB-199 row / a test fixture) is treated as `local`.
169
+ */
170
+ source?: MemberSource;
171
+ /** The principal subject that issued the invite, if any. */
172
+ invitedBy: string | null;
173
+ createdAt: string;
174
+ }
175
+ /**
176
+ * One per-page ACL grant — a row of the `page_acl` table (OB-182 §2.3). Exactly
177
+ * one grantee key is set: `subject` (a grantee already bound to any trusted issuer)
178
+ * XOR `email` (a grantee by persona email, lowercased). An email grant MUST pin an
179
+ * `issuer` (the email-authority — B1).
180
+ */
181
+ export interface PageAcl {
182
+ pageId: string;
183
+ subject: string | null;
184
+ email: string | null;
185
+ issuer: string | null;
186
+ level: AclLevel;
187
+ invitedBy: string | null;
188
+ createdAt: string;
189
+ }
99
190
  /** Status of a desktop install's local server. */
100
191
  export interface ServerInfo {
101
192
  /** Whether the local server is currently running. */
package/dist/types.js CHANGED
@@ -13,4 +13,13 @@ export const emptyPageSnapshot = () => ({
13
13
  values: [],
14
14
  names: [],
15
15
  });
16
+ /** Every {@link PageVisibility} value, in escalating-privacy order — the source of
17
+ * truth for server-side validation and the share dialog's scope picker. */
18
+ export const PAGE_VISIBILITIES = [
19
+ 'inherit',
20
+ 'public',
21
+ 'authenticated',
22
+ 'members',
23
+ 'restricted',
24
+ ];
16
25
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4BH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAiB,EAAE,CAAC,CAAC;IACpD,QAAQ,EAAE,EAAC,MAAM,EAAE,EAAE,EAAC;IACtB,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,EAAE;CACV,CAAC,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAqCH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAiB,EAAE,CAAC,CAAC;IACpD,QAAQ,EAAE,EAAC,MAAM,EAAE,EAAE,EAAC;IACtB,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,EAAE;CACV,CAAC,CAAC;AAuFH;4EAC4E;AAC5E,MAAM,CAAC,MAAM,iBAAiB,GAA8B;IAC1D,SAAS;IACT,QAAQ;IACR,eAAe;IACf,SAAS;IACT,YAAY;CACb,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@book.dev/sdk",
3
- "version": "1.60.0",
3
+ "version": "1.64.0",
4
4
  "description": "Shared OpenBook types and HTTP client used by the server, desktop, and web.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/eliotlim/OpenBook.git",
8
+ "directory": "packages/sdk"
9
+ },
5
10
  "publishConfig": {
6
11
  "access": "public"
7
12
  },