@hatk/hatk 0.0.1-alpha.10 → 0.0.1-alpha.101

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 (222) hide show
  1. package/dist/adapter.d.ts +19 -0
  2. package/dist/adapter.d.ts.map +1 -0
  3. package/dist/adapter.js +113 -0
  4. package/dist/backfill.d.ts +32 -2
  5. package/dist/backfill.d.ts.map +1 -1
  6. package/dist/backfill.js +154 -51
  7. package/dist/car.d.ts +20 -0
  8. package/dist/car.d.ts.map +1 -1
  9. package/dist/car.js +108 -0
  10. package/dist/cli.js +247 -1043
  11. package/dist/config.d.ts +145 -1
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +61 -8
  14. package/dist/database/adapter-factory.d.ts +6 -0
  15. package/dist/database/adapter-factory.d.ts.map +1 -0
  16. package/dist/database/adapter-factory.js +20 -0
  17. package/dist/database/adapters/duckdb-search.d.ts +12 -0
  18. package/dist/database/adapters/duckdb-search.d.ts.map +1 -0
  19. package/dist/database/adapters/duckdb-search.js +27 -0
  20. package/dist/database/adapters/duckdb.d.ts +25 -0
  21. package/dist/database/adapters/duckdb.d.ts.map +1 -0
  22. package/dist/database/adapters/duckdb.js +161 -0
  23. package/dist/database/adapters/sqlite-search.d.ts +16 -0
  24. package/dist/database/adapters/sqlite-search.d.ts.map +1 -0
  25. package/dist/database/adapters/sqlite-search.js +76 -0
  26. package/dist/database/adapters/sqlite.d.ts +18 -0
  27. package/dist/database/adapters/sqlite.d.ts.map +1 -0
  28. package/dist/database/adapters/sqlite.js +88 -0
  29. package/dist/{db.d.ts → database/db.d.ts} +94 -6
  30. package/dist/database/db.d.ts.map +1 -0
  31. package/dist/database/db.js +1833 -0
  32. package/dist/database/dialect.d.ts +45 -0
  33. package/dist/database/dialect.d.ts.map +1 -0
  34. package/dist/database/dialect.js +72 -0
  35. package/dist/{fts.d.ts → database/fts.d.ts} +7 -0
  36. package/dist/database/fts.d.ts.map +1 -0
  37. package/dist/{fts.js → database/fts.js} +122 -34
  38. package/dist/database/index.d.ts +7 -0
  39. package/dist/database/index.d.ts.map +1 -0
  40. package/dist/database/index.js +6 -0
  41. package/dist/database/ports.d.ts +50 -0
  42. package/dist/database/ports.d.ts.map +1 -0
  43. package/dist/database/ports.js +1 -0
  44. package/dist/database/schema.d.ts +91 -0
  45. package/dist/database/schema.d.ts.map +1 -0
  46. package/dist/{schema.js → database/schema.js} +153 -54
  47. package/dist/dev-entry.d.ts +8 -0
  48. package/dist/dev-entry.d.ts.map +1 -0
  49. package/dist/dev-entry.js +126 -0
  50. package/dist/feeds.d.ts +26 -8
  51. package/dist/feeds.d.ts.map +1 -1
  52. package/dist/feeds.js +72 -16
  53. package/dist/hooks.d.ts +102 -0
  54. package/dist/hooks.d.ts.map +1 -0
  55. package/dist/hooks.js +186 -0
  56. package/dist/hydrate.d.ts +55 -6
  57. package/dist/hydrate.d.ts.map +1 -1
  58. package/dist/hydrate.js +21 -20
  59. package/dist/indexer.d.ts +194 -3
  60. package/dist/indexer.d.ts.map +1 -1
  61. package/dist/indexer.js +620 -92
  62. package/dist/jetstream.d.ts +118 -0
  63. package/dist/jetstream.d.ts.map +1 -0
  64. package/dist/jetstream.js +238 -0
  65. package/dist/labels.d.ts +36 -0
  66. package/dist/labels.d.ts.map +1 -1
  67. package/dist/labels.js +71 -6
  68. package/dist/lex-types.d.ts +2 -0
  69. package/dist/lex-types.d.ts.map +1 -1
  70. package/dist/lexicon-resolve.d.ts.map +1 -1
  71. package/dist/lexicon-resolve.js +27 -112
  72. package/dist/lexicons/com/atproto/label/defs.json +75 -0
  73. package/dist/lexicons/com/atproto/moderation/defs.json +30 -0
  74. package/dist/lexicons/com/atproto/repo/strongRef.json +21 -0
  75. package/dist/lexicons/dev/hatk/applyWrites.json +87 -0
  76. package/dist/lexicons/dev/hatk/createRecord.json +40 -0
  77. package/dist/lexicons/dev/hatk/createReport.json +48 -0
  78. package/dist/lexicons/dev/hatk/deleteRecord.json +25 -0
  79. package/dist/lexicons/dev/hatk/describeCollections.json +41 -0
  80. package/dist/lexicons/dev/hatk/describeFeeds.json +29 -0
  81. package/dist/lexicons/dev/hatk/describeLabels.json +45 -0
  82. package/dist/lexicons/dev/hatk/getFeed.json +30 -0
  83. package/dist/lexicons/dev/hatk/getPreferences.json +19 -0
  84. package/dist/lexicons/dev/hatk/getRecord.json +26 -0
  85. package/dist/lexicons/dev/hatk/getRecords.json +32 -0
  86. package/dist/lexicons/dev/hatk/putPreference.json +28 -0
  87. package/dist/lexicons/dev/hatk/putRecord.json +41 -0
  88. package/dist/lexicons/dev/hatk/searchRecords.json +32 -0
  89. package/dist/lexicons/dev/hatk/uploadBlob.json +23 -0
  90. package/dist/logger.d.ts +29 -0
  91. package/dist/logger.d.ts.map +1 -1
  92. package/dist/logger.js +29 -0
  93. package/dist/main.js +196 -75
  94. package/dist/mst.d.ts +15 -0
  95. package/dist/mst.d.ts.map +1 -1
  96. package/dist/mst.js +13 -0
  97. package/dist/oauth/db.d.ts +27 -1
  98. package/dist/oauth/db.d.ts.map +1 -1
  99. package/dist/oauth/db.js +80 -19
  100. package/dist/oauth/discovery.d.ts +10 -0
  101. package/dist/oauth/discovery.d.ts.map +1 -1
  102. package/dist/oauth/discovery.js +54 -2
  103. package/dist/oauth/server.d.ts +131 -1
  104. package/dist/oauth/server.d.ts.map +1 -1
  105. package/dist/oauth/server.js +504 -39
  106. package/dist/oauth/service-describe.d.ts +42 -0
  107. package/dist/oauth/service-describe.d.ts.map +1 -0
  108. package/dist/oauth/service-describe.js +108 -0
  109. package/dist/oauth/session.d.ts +32 -0
  110. package/dist/oauth/session.d.ts.map +1 -0
  111. package/dist/oauth/session.js +131 -0
  112. package/dist/opengraph.d.ts +10 -0
  113. package/dist/opengraph.d.ts.map +1 -1
  114. package/dist/opengraph.js +94 -42
  115. package/dist/pds-proxy.d.ts +92 -0
  116. package/dist/pds-proxy.d.ts.map +1 -0
  117. package/dist/pds-proxy.js +396 -0
  118. package/dist/private-collections.d.ts +13 -0
  119. package/dist/private-collections.d.ts.map +1 -0
  120. package/dist/private-collections.js +27 -0
  121. package/dist/push.d.ts +54 -0
  122. package/dist/push.d.ts.map +1 -0
  123. package/dist/push.js +367 -0
  124. package/dist/renderer.d.ts +27 -0
  125. package/dist/renderer.d.ts.map +1 -0
  126. package/dist/renderer.js +46 -0
  127. package/dist/resolve-hatk.d.ts +6 -0
  128. package/dist/resolve-hatk.d.ts.map +1 -0
  129. package/dist/resolve-hatk.js +20 -0
  130. package/dist/response.d.ts +16 -0
  131. package/dist/response.d.ts.map +1 -0
  132. package/dist/response.js +69 -0
  133. package/dist/scanner.d.ts +21 -0
  134. package/dist/scanner.d.ts.map +1 -0
  135. package/dist/scanner.js +88 -0
  136. package/dist/seed.d.ts +19 -0
  137. package/dist/seed.d.ts.map +1 -1
  138. package/dist/seed.js +43 -4
  139. package/dist/server-init.d.ts +8 -0
  140. package/dist/server-init.d.ts.map +1 -0
  141. package/dist/server-init.js +62 -0
  142. package/dist/server.d.ts +34 -3
  143. package/dist/server.d.ts.map +1 -1
  144. package/dist/server.js +1033 -649
  145. package/dist/setup.d.ts +28 -1
  146. package/dist/setup.d.ts.map +1 -1
  147. package/dist/setup.js +50 -3
  148. package/dist/spaces/blob.d.ts +112 -0
  149. package/dist/spaces/blob.d.ts.map +1 -0
  150. package/dist/spaces/blob.js +460 -0
  151. package/dist/spaces/credential.d.ts +66 -0
  152. package/dist/spaces/credential.d.ts.map +1 -0
  153. package/dist/spaces/credential.js +175 -0
  154. package/dist/spaces/engine.d.ts +97 -0
  155. package/dist/spaces/engine.d.ts.map +1 -0
  156. package/dist/spaces/engine.js +563 -0
  157. package/dist/spaces/guard.d.ts +41 -0
  158. package/dist/spaces/guard.d.ts.map +1 -0
  159. package/dist/spaces/guard.js +79 -0
  160. package/dist/spaces/identity.d.ts +37 -0
  161. package/dist/spaces/identity.d.ts.map +1 -0
  162. package/dist/spaces/identity.js +88 -0
  163. package/dist/spaces/index.d.ts +55 -0
  164. package/dist/spaces/index.d.ts.map +1 -0
  165. package/dist/spaces/index.js +133 -0
  166. package/dist/spaces/notify.d.ts +60 -0
  167. package/dist/spaces/notify.d.ts.map +1 -0
  168. package/dist/spaces/notify.js +128 -0
  169. package/dist/spaces/records.d.ts +37 -0
  170. package/dist/spaces/records.d.ts.map +1 -0
  171. package/dist/spaces/records.js +63 -0
  172. package/dist/spaces/signature.d.ts +36 -0
  173. package/dist/spaces/signature.d.ts.map +1 -0
  174. package/dist/spaces/signature.js +83 -0
  175. package/dist/spaces/store.d.ts +51 -0
  176. package/dist/spaces/store.d.ts.map +1 -0
  177. package/dist/spaces/store.js +99 -0
  178. package/dist/spaces/uri.d.ts +60 -0
  179. package/dist/spaces/uri.d.ts.map +1 -0
  180. package/dist/spaces/uri.js +97 -0
  181. package/dist/spaces/verify.d.ts +46 -0
  182. package/dist/spaces/verify.d.ts.map +1 -0
  183. package/dist/spaces/verify.js +94 -0
  184. package/dist/spaces/viewer.d.ts +51 -0
  185. package/dist/spaces/viewer.d.ts.map +1 -0
  186. package/dist/spaces/viewer.js +167 -0
  187. package/dist/spaces/visibility.d.ts +57 -0
  188. package/dist/spaces/visibility.d.ts.map +1 -0
  189. package/dist/spaces/visibility.js +81 -0
  190. package/dist/templates/feed.tpl +18 -0
  191. package/dist/templates/hook.tpl +5 -0
  192. package/dist/templates/label.tpl +15 -0
  193. package/dist/templates/og.tpl +17 -0
  194. package/dist/templates/seed.tpl +11 -0
  195. package/dist/templates/setup.tpl +5 -0
  196. package/dist/templates/test-feed.tpl +19 -0
  197. package/dist/templates/test-xrpc.tpl +19 -0
  198. package/dist/templates/xrpc.tpl +53 -0
  199. package/dist/test.d.ts +3 -1
  200. package/dist/test.d.ts.map +1 -1
  201. package/dist/test.js +60 -36
  202. package/dist/views.js +1 -1
  203. package/dist/vite-plugin.d.ts +1 -1
  204. package/dist/vite-plugin.d.ts.map +1 -1
  205. package/dist/vite-plugin.js +254 -66
  206. package/dist/xrpc.d.ts +122 -12
  207. package/dist/xrpc.d.ts.map +1 -1
  208. package/dist/xrpc.js +270 -55
  209. package/package.json +28 -9
  210. package/public/admin-auth.js +271 -306
  211. package/public/admin.html +177 -61
  212. package/dist/db.d.ts.map +0 -1
  213. package/dist/db.js +0 -1361
  214. package/dist/fts.d.ts.map +0 -1
  215. package/dist/oauth/hooks.d.ts +0 -10
  216. package/dist/oauth/hooks.d.ts.map +0 -1
  217. package/dist/oauth/hooks.js +0 -40
  218. package/dist/schema.d.ts +0 -51
  219. package/dist/schema.d.ts.map +0 -1
  220. package/dist/test-browser.d.ts +0 -14
  221. package/dist/test-browser.d.ts.map +0 -1
  222. package/dist/test-browser.js +0 -26
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Getting into a space to read it.
3
+ *
4
+ * hatk is not a member of anything. It has no DID that any community has
5
+ * admitted, and asking every authority to admit an indexer would make indexing
6
+ * a per-community act of trust before a single record could be read.
7
+ *
8
+ * So it reads as somebody who is already inside: a viewer whose OAuth session
9
+ * it already holds, whose PDS will mint a delegation token for the space, and
10
+ * whom the authority already lets in. The exchange is the same one the
11
+ * community's own web app makes from the browser —
12
+ *
13
+ * the reader's PDS signs a delegation token (60s, single-use, addressed to
14
+ * the authority's space host)
15
+ * the authority checks it, checks the reader against the space's policy, and
16
+ * returns a credential bound to the key that signed the exchange (10 min)
17
+ *
18
+ * — and the credential is then presented to every writer's host in the space.
19
+ * It carries no audience, which is why it must be bound to a key rather than
20
+ * held as a bearer token: each request signs the credential together with the
21
+ * DID it is addressed to, so a host handed one to serve its own repo cannot
22
+ * replay it against any other account. See signature.ts.
23
+ *
24
+ * The consequence to be honest about: a space is only readable while somebody
25
+ * who can read it has a live session here. That is the same bound the data has
26
+ * anyway — nobody outside the space's audience was ever entitled to this — but
27
+ * it does mean indexing lapses when the last member logs out.
28
+ */
29
+ import { pdsXrpc } from "../pds-proxy.js";
30
+ import { emit } from "../logger.js";
31
+ import { spaceHostEndpoint } from "./identity.js";
32
+ import { generateSpaceSigKey, spaceSigHeaders } from "./signature.js";
33
+ import { parseSpaceRef } from "./uri.js";
34
+ /**
35
+ * Re-mint this long before the credential's own expiry rather than racing it.
36
+ * Credentials live ten minutes, so this keeps nine of them.
37
+ */
38
+ const RENEW_LEAD_MS = 60 * 1000;
39
+ export class SpaceCredentialError extends Error {
40
+ status;
41
+ code;
42
+ constructor(status, code, message) {
43
+ super(message);
44
+ this.status = status;
45
+ this.code = code;
46
+ }
47
+ }
48
+ /** A refusal about who is asking, rather than about the space or the network. */
49
+ export function isNotAuthorized(err) {
50
+ return err instanceof SpaceCredentialError && (err.code === 'UserNotAuthorized' || err.code === 'NotAuthorized');
51
+ }
52
+ export function isSpaceGone(err) {
53
+ return err instanceof SpaceCredentialError && (err.code === 'SpaceDeleted' || err.code === 'SpaceNotFound');
54
+ }
55
+ function expiryOf(jwt) {
56
+ try {
57
+ const payload = JSON.parse(Buffer.from(jwt.split('.')[1], 'base64url').toString());
58
+ return typeof payload.exp === 'number' ? payload.exp * 1000 : Date.now() + 60 * 60 * 1000;
59
+ }
60
+ catch {
61
+ // An unreadable expiry is not a reason to refuse a credential the authority
62
+ // just issued; treat it as short-lived and re-mint sooner.
63
+ return Date.now() + 10 * 60 * 1000;
64
+ }
65
+ }
66
+ /**
67
+ * Exchange a delegation token for a credential at the authority, binding it to
68
+ * `key` by signing the token with it.
69
+ */
70
+ async function exchange(authorityHost, space, delegationToken, key) {
71
+ const url = `${authorityHost}/xrpc/com.atproto.space.getSpaceCredential`;
72
+ const res = await fetch(url, {
73
+ method: 'POST',
74
+ headers: {
75
+ 'Content-Type': 'application/json',
76
+ Accept: 'application/json',
77
+ ...(await spaceSigHeaders(key, `Bearer ${delegationToken}`)),
78
+ },
79
+ body: JSON.stringify({ space }),
80
+ });
81
+ const body = (await res.json().catch(() => ({})));
82
+ if (!res.ok || !body.credential) {
83
+ throw new SpaceCredentialError(res.status, body.error ?? (res.status >= 500 ? 'UpstreamFailure' : 'InvalidRequest'), body.message ?? `getSpaceCredential refused (${res.status})`);
84
+ }
85
+ return body.credential;
86
+ }
87
+ /** Mint a credential for `space` using `readerDid`'s stored session. */
88
+ export async function mintSpaceCredential(oauthConfig, space, readerDid) {
89
+ const ref = parseSpaceRef(space);
90
+ if (!ref)
91
+ throw new SpaceCredentialError(400, 'InvalidRequest', `Not a space ref: ${space}`);
92
+ // The reader's own PDS signs this, under the whole-space read grant their
93
+ // session carries. A session without that scope is refused here, before the
94
+ // authority is ever contacted.
95
+ let token;
96
+ try {
97
+ const out = await pdsXrpc(oauthConfig, { did: readerDid }, 'com.atproto.space.getDelegationToken', {
98
+ params: { space },
99
+ });
100
+ if (typeof out.token !== 'string')
101
+ throw new Error('PDS returned no delegation token');
102
+ token = out.token;
103
+ }
104
+ catch (err) {
105
+ throw new SpaceCredentialError(err?.status ?? 502, 'DelegationFailed', err?.message ?? 'delegation failed');
106
+ }
107
+ // A key per credential, held only as long as the credential is.
108
+ const key = await generateSpaceSigKey();
109
+ const authorityHost = await spaceHostEndpoint(ref.authority);
110
+ const credential = await exchange(authorityHost, space, token, key);
111
+ // Signatures depend only on the credential and the audience, so each is made
112
+ // once and reused for as long as the credential lives.
113
+ const signed = new Map();
114
+ const credentialFetch = async (input, init) => {
115
+ const url = typeof input === 'string' ? input : input.toString();
116
+ const audience = new URL(url).searchParams.get('repo') ?? ref.authority;
117
+ let sig = signed.get(audience);
118
+ if (!sig) {
119
+ sig = spaceSigHeaders(key, `Atproto-Space ${credential}`, audience);
120
+ signed.set(audience, sig);
121
+ }
122
+ const headers = new Headers(init?.headers);
123
+ for (const [name, value] of Object.entries(await sig))
124
+ headers.set(name, value);
125
+ return fetch(url, { ...init, headers });
126
+ };
127
+ return { space, readerDid, expiresAt: expiryOf(credential), fetch: credentialFetch };
128
+ }
129
+ // --- Cache ---
130
+ const cache = new Map();
131
+ function fresh(cred) {
132
+ return !!cred && cred.expiresAt - RENEW_LEAD_MS > Date.now();
133
+ }
134
+ /**
135
+ * A credential for `space`, minted with whichever candidate session works.
136
+ *
137
+ * Candidates are tried in order and the first that succeeds is cached. A
138
+ * refusal about the reader — they were ejected, or never belonged — moves on to
139
+ * the next candidate; a refusal about the space itself stops the whole attempt,
140
+ * since no other reader would fare better.
141
+ */
142
+ export async function getSpaceCredential(oauthConfig, space, candidates, opts = {}) {
143
+ if (!opts.refresh) {
144
+ const cached = cache.get(space);
145
+ if (fresh(cached))
146
+ return cached;
147
+ }
148
+ let lastError;
149
+ for (const readerDid of candidates) {
150
+ try {
151
+ const credential = await mintSpaceCredential(oauthConfig, space, readerDid);
152
+ cache.set(space, credential);
153
+ return credential;
154
+ }
155
+ catch (err) {
156
+ if (isSpaceGone(err))
157
+ throw err;
158
+ lastError = err;
159
+ emit('spaces', 'credential_refused', {
160
+ space,
161
+ reader_did: readerDid,
162
+ error: err instanceof Error ? err.message : String(err),
163
+ });
164
+ }
165
+ }
166
+ cache.delete(space);
167
+ throw lastError ?? new SpaceCredentialError(403, 'NoReader', `No session on this instance can read ${space}`);
168
+ }
169
+ export function forgetSpaceCredential(space) {
170
+ cache.delete(space);
171
+ }
172
+ /** For tests: drop every cached credential. */
173
+ export function resetSpaceCredentials() {
174
+ cache.clear();
175
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Keeping the index level with a permissioned space.
3
+ *
4
+ * A space never reaches a firehose. There is no stream to tail and no relay
5
+ * that has seen it, so the only way to know a space has moved is to ask the
6
+ * authority who has written into it and then ask each of those writers' hosts
7
+ * what changed. Two loops do that:
8
+ *
9
+ * reconcile the authority's `listRepos` gives the writer set with each
10
+ * writer's current rev. Anything whose rev has moved is synced;
11
+ * anything the authority no longer names is dropped.
12
+ * sync one writer's repo, forward from the rev we last read, through
13
+ * `listRepoOps` — or wholesale through `listRecords` when there
14
+ * is no rev to start from, or when the op log has been compacted
15
+ * past it.
16
+ *
17
+ * Write notices exist too and are far cheaper, but they are best-effort by
18
+ * design: the reference host forwards them once from an in-memory queue and
19
+ * logs the failure. So reconcile is the thing that makes sync correct, and a
20
+ * notice only makes it prompt.
21
+ *
22
+ * What is deliberately not done here is verification. The alpha signs a commit
23
+ * over the repo's LtHash state, and a syncer can check it. hatk does not check
24
+ * the equivalent on the firehose path either — it reads records out of relayed
25
+ * CAR blocks and trusts them — so checking here would claim a guarantee the
26
+ * rest of the index does not make. Adding it means depending on `@atproto/space`
27
+ * for LtHash and the commit verifier, and is worth doing to both paths at once
28
+ * rather than to this one alone.
29
+ */
30
+ import type { OAuthConfig } from '../config.ts';
31
+ import { type SpaceCredential } from './credential.ts';
32
+ import { type SpaceWatch } from './store.ts';
33
+ export interface SpaceEngineOptions {
34
+ oauth: OAuthConfig;
35
+ /** Space type NSIDs this instance will follow. Anything else is refused. */
36
+ types: Set<string>;
37
+ /** Collections hatk indexes at all; a space collection outside this is skipped. */
38
+ collections: Set<string>;
39
+ /**
40
+ * This instance's service identifier — `did:web:...#atproto_space_syncer`.
41
+ * Absent when the instance receives no notices, in which case the sweep is
42
+ * the only thing that notices a write.
43
+ */
44
+ serviceId?: string;
45
+ }
46
+ export declare function configureSpaceEngine(opts: SpaceEngineOptions): void;
47
+ /**
48
+ * The collections a space of this type holds, narrowed to the ones hatk has a
49
+ * table for.
50
+ *
51
+ * A space type's lexicon declares its collections, which is what makes a space
52
+ * readable without the app being told what is in it — but a space may name
53
+ * collections this instance does not index, and those are simply not its
54
+ * business.
55
+ */
56
+ export declare function collectionsForSpaceType(spaceType: string): string[];
57
+ /** Bring one writer's repo in a space up to date, however that has to happen. */
58
+ export declare function syncSpaceRepo(watch: SpaceWatch, writer: string, credential: SpaceCredential): Promise<void>;
59
+ /**
60
+ * Compare the authority's writer set against what the index holds, and close
61
+ * the difference.
62
+ *
63
+ * The writer set is what the authority has been told, not what is true: a
64
+ * repo's own host is the source of truth, and after a community migrates hosts
65
+ * the set is empty until each writer writes again. So a writer the authority
66
+ * stops naming has their rows dropped, but the rev comparison is only ever a
67
+ * reason to read — never a reason to believe a repo has not moved.
68
+ */
69
+ export declare function reconcileSpace(watch: SpaceWatch): Promise<void>;
70
+ /** Follow a space from now on, and read it once. */
71
+ export declare function watchSpace(space: string): Promise<SpaceWatch>;
72
+ /** Stop following a space and drop everything indexed from it. */
73
+ export declare function unwatchSpace(space: string): Promise<void>;
74
+ /**
75
+ * Act on a write notice: read the one repo it names.
76
+ *
77
+ * Only for a space already followed. A notice about anything else is not an
78
+ * instruction to start following it — that decision belongs to config or to the
79
+ * app, never to whoever can reach this endpoint.
80
+ *
81
+ * The notice's `rev` is deliberately not trusted as the new position: it is
82
+ * read from the repo's own host, which is the source of truth, by the ordinary
83
+ * sync path. The notice only says "look again".
84
+ */
85
+ export declare function handleWriteNotice(notice: {
86
+ space: string;
87
+ repo: string;
88
+ }): Promise<boolean>;
89
+ /**
90
+ * Reconcile every followed space.
91
+ *
92
+ * Failures are per space and recorded rather than thrown: one community's host
93
+ * being unreachable is not a reason to stop reading the others, and a space
94
+ * whose last reader logged out should go quiet rather than take the sweep down.
95
+ */
96
+ export declare function reconcileAll(): Promise<void>;
97
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/spaces/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAQ/C,OAAO,EAA0D,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAE9G,OAAO,EAUL,KAAK,UAAU,EAChB,MAAM,YAAY,CAAA;AAMnB,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,WAAW,CAAA;IAClB,4EAA4E;IAC5E,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAClB,mFAAmF;IACnF,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAaD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAEnE;AAOD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAQnE;AAqUD,iFAAiF;AACjF,wBAAsB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBjH;AAqED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCrE;AAID,oDAAoD;AACpD,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAUnE;AAED,kEAAkE;AAClE,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAKjG;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAclD"}