@abloatai/ablo 0.11.2 → 0.13.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.
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +34 -0
- package/README.md +3 -3
- package/dist/ai-sdk/claim-broadcast.d.ts +4 -3
- package/dist/ai-sdk/claim-broadcast.js +2 -2
- package/dist/ai-sdk/wrap.d.ts +5 -4
- package/dist/ai-sdk/wrap.js +3 -3
- package/dist/cli.cjs +152 -41
- package/dist/client/Ablo.d.ts +25 -3
- package/dist/client/Ablo.js +5 -5
- package/dist/client/ApiClient.js +26 -11
- package/dist/client/createModelProxy.d.ts +15 -7
- package/dist/client/createModelProxy.js +12 -12
- package/dist/coordination/schema.d.ts +1 -1
- package/dist/coordination/schema.js +3 -1
- package/dist/errors.d.ts +3 -1
- package/dist/errors.js +6 -1
- package/dist/react/AbloProvider.d.ts +11 -7
- package/dist/react/AbloProvider.js +9 -5
- package/dist/react/context.d.ts +9 -14
- package/dist/react/context.js +10 -15
- package/dist/react/index.d.ts +8 -4
- package/dist/react/index.js +8 -4
- package/dist/react/useMutators.js +3 -2
- package/dist/react/useUndoScope.js +3 -2
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +2 -2
- package/dist/schema/model.d.ts +38 -77
- package/dist/schema/model.js +12 -12
- package/dist/schema/roles.d.ts +49 -0
- package/dist/schema/roles.js +21 -0
- package/dist/schema/schema.d.ts +1 -1
- package/dist/schema/schema.js +1 -1
- package/dist/schema/serialize.d.ts +4 -2
- package/dist/schema/serialize.js +4 -2
- package/dist/schema/sugar.d.ts +7 -28
- package/dist/schema/sugar.js +2 -7
- package/dist/schema/sync-delta-row.d.ts +2 -0
- package/dist/schema/sync-delta-row.js +2 -1
- package/dist/schema/tenancy.d.ts +67 -28
- package/dist/schema/tenancy.js +93 -23
- package/dist/server/commit.d.ts +8 -3
- package/dist/sync/createClaimStream.js +5 -4
- package/dist/sync/participants.js +1 -1
- package/dist/types/streams.d.ts +17 -7
- package/docs/api.md +1 -1
- package/docs/cli.md +43 -4
- package/docs/client-behavior.md +2 -2
- package/docs/coordination.md +1 -1
- package/docs/examples/agent-human.md +6 -6
- package/docs/examples/ai-sdk-tool.md +1 -1
- package/docs/examples/existing-python-backend.md +0 -2
- package/docs/examples/nextjs.md +2 -2
- package/docs/examples/scoped-agent.md +3 -3
- package/docs/examples/server-agent.md +4 -4
- package/docs/identity.md +27 -20
- package/docs/index.md +0 -1
- package/docs/integration-guide.md +12 -9
- package/docs/interaction-model.md +1 -1
- package/docs/mcp.md +17 -5
- package/docs/migration.md +2 -1
- package/docs/quickstart.md +3 -3
- package/llms.txt +2 -3
- package/package.json +3 -2
- package/docs/mcp/claude-code.md +0 -35
- package/docs/mcp/cursor.md +0 -35
- package/docs/mcp/windsurf.md +0 -33
- package/docs/roadmap.md +0 -55
- package/docs/the-loop.md +0 -21
- package/llms-full.txt +0 -396
|
@@ -142,20 +142,23 @@ model(
|
|
|
142
142
|
},
|
|
143
143
|
/* relations */ {},
|
|
144
144
|
{
|
|
145
|
-
//
|
|
146
|
-
|
|
145
|
+
// Axis 1 — `policy`: who may READ a row (tenant isolation / RLS). A
|
|
146
|
+
// row-local `organization_id` column is the default, so you omit this for
|
|
147
|
+
// normal tables; set it only for the exceptions (parent-inherited / global).
|
|
147
148
|
|
|
149
|
+
// Axis 2 — `groups`: which sync-group CHANNELS a row fans into.
|
|
148
150
|
// Scope root: rows form the group `matter:<id>`. Children point at it with
|
|
149
151
|
// `relation.belongsTo('matters', 'matterId', { parent: true })` to inherit.
|
|
150
|
-
|
|
152
|
+
groups: { root: 'matter' },
|
|
151
153
|
}
|
|
152
154
|
);
|
|
153
155
|
```
|
|
154
156
|
|
|
155
|
-
For rows that don't carry `organization_id` themselves but inherit
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
For rows that don't carry `organization_id` themselves but inherit tenancy via a
|
|
158
|
+
foreign key, set `policy: { by: 'parent', fk: '<fk>', parent: '<parentTable>' }`.
|
|
159
|
+
For genuinely global/reference data, `policy: { by: 'none' }`. ⚠ `by: 'none'`
|
|
160
|
+
exposes the whole table cross-tenant, so it's an explicit, named branch — never a
|
|
161
|
+
falsy flag. See `packages/sync-engine/src/schema/model.ts` for the full option set.
|
|
159
162
|
|
|
160
163
|
## 2. Create The Client
|
|
161
164
|
|
|
@@ -444,7 +447,7 @@ scope.
|
|
|
444
447
|
```ts
|
|
445
448
|
await using claim = await ablo.weatherReports.claim({
|
|
446
449
|
id: reportId,
|
|
447
|
-
|
|
450
|
+
reason: 'forecasting',
|
|
448
451
|
});
|
|
449
452
|
const claimed = claim.data;
|
|
450
453
|
if (!claimed) return;
|
|
@@ -510,7 +513,7 @@ them.
|
|
|
510
513
|
| `update({ id, data, ...opts })` | Update through the model client. |
|
|
511
514
|
| `delete({ id, ...opts })` | Delete through the model client. |
|
|
512
515
|
| `claim.state({ id })` | See who is currently working on a row (synchronous). |
|
|
513
|
-
| `claim({ id,
|
|
516
|
+
| `claim({ id, reason?, ttl? })` | Acquire a disposable handle: wait for your turn, re-read, and hold the row. |
|
|
514
517
|
|
|
515
518
|
Keep first integrations on the model methods above. Every mutation and
|
|
516
519
|
server-read verb takes one options object; only the synchronous `get(id)` stays
|
|
@@ -70,7 +70,7 @@ automatically when the scope exits:
|
|
|
70
70
|
```ts
|
|
71
71
|
await using claim = await ablo.weatherReports.claim({
|
|
72
72
|
id: 'report_stockholm',
|
|
73
|
-
|
|
73
|
+
reason: 'editing',
|
|
74
74
|
});
|
|
75
75
|
await ablo.weatherReports.update({ id: claim.data.id, data: { status: 'ready' } }); // rejected if the row changed under the claim
|
|
76
76
|
```
|
package/docs/mcp.md
CHANGED
|
@@ -67,11 +67,23 @@ Point your assistant at the hosted endpoint — no auth, no token:
|
|
|
67
67
|
claude mcp add --transport http ablo https://<your-app>/api/mcp
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
The endpoint is identical for every client — only the config surface differs:
|
|
71
71
|
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
72
|
+
- **Claude Code** — run the `claude mcp add` command above; verify with `/mcp list`, remove with `claude mcp remove ablo`.
|
|
73
|
+
- **Cursor** — add the server to `~/.cursor/mcp.json` (macOS / Linux), then restart.
|
|
74
|
+
- **Windsurf** — add the same JSON via Settings → Cascade → MCP, then restart.
|
|
75
|
+
|
|
76
|
+
Cursor and Windsurf use the same config shape:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"ablo": { "transport": "http", "url": "https://<your-app>/api/mcp" }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Each client then lists the Ablo tools (`search_ablo_docs`, `get_recipe`, `get_api_surface`, `validate_schema`, `scaffold_app`) in its MCP panel.
|
|
75
87
|
|
|
76
88
|
### What it exposes
|
|
77
89
|
|
|
@@ -96,7 +108,7 @@ loading everything into context.
|
|
|
96
108
|
Reusable, parameterised templates that drive an end-to-end flow:
|
|
97
109
|
|
|
98
110
|
- `integrate-sync-engine` — wire the SDK into an existing project.
|
|
99
|
-
- `add-agent` — add an agent worker that coordinates via
|
|
111
|
+
- `add-agent` — add an agent worker that coordinates via claims and
|
|
100
112
|
conflict-safe writes.
|
|
101
113
|
- `define-schema` — design a Zod-first schema from a description, then run
|
|
102
114
|
`validate_schema` before committing.
|
package/docs/migration.md
CHANGED
|
@@ -284,7 +284,8 @@ One provider component now owns the full React lifecycle. `<SyncProvider>`,
|
|
|
284
284
|
- <SyncProvider store={sync._store} organizationId={orgId}>
|
|
285
285
|
- <AbloProvider ablo={ablo}>{children}</AbloProvider>
|
|
286
286
|
- </SyncProvider>
|
|
287
|
-
+
|
|
287
|
+
+ const ablo = Ablo({ schema, apiKey });
|
|
288
|
+
+ <AbloProvider client={ablo}>
|
|
288
289
|
+ {children}
|
|
289
290
|
+ </AbloProvider>
|
|
290
291
|
```
|
package/docs/quickstart.md
CHANGED
|
@@ -222,7 +222,7 @@ Call `handle.release()` when your work is done.
|
|
|
222
222
|
// Claim the row so other participants serialize behind us while we work.
|
|
223
223
|
const handle = await ablo.weatherReports.claim({
|
|
224
224
|
id: 'weather_stockholm',
|
|
225
|
-
|
|
225
|
+
reason: 'checking_weather',
|
|
226
226
|
ttl: '2m',
|
|
227
227
|
});
|
|
228
228
|
|
|
@@ -260,7 +260,7 @@ write through the model.
|
|
|
260
260
|
```ts
|
|
261
261
|
const active = ablo.weatherReports.claim.state({ id: 'weather_stockholm' });
|
|
262
262
|
if (active) {
|
|
263
|
-
console.log(`${active.heldBy} is ${active.
|
|
263
|
+
console.log(`${active.heldBy} is ${active.reason}`);
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
const handle = await ablo.weatherReports.claim({ id: 'weather_stockholm' });
|
|
@@ -268,7 +268,7 @@ await ablo.weatherReports.update({ id: handle.data.id, data: { status: 'ready' }
|
|
|
268
268
|
await handle.release();
|
|
269
269
|
```
|
|
270
270
|
|
|
271
|
-
Use `{
|
|
271
|
+
Use `{ queue: false }` on `claim` when work should be skipped instead of queued
|
|
272
272
|
behind an active holder.
|
|
273
273
|
|
|
274
274
|
## Next steps
|
package/llms.txt
CHANGED
|
@@ -12,7 +12,7 @@ First action when integrating into an app: run `npx ablo init --yes --framework
|
|
|
12
12
|
|
|
13
13
|
Second: make sure a key exists — WITHOUT printing it. The key is a secret; it must never appear in your output, your reasoning, or a file you echo (it would live in the conversation history forever). Check PRESENCE only: `[ -n "$ABLO_API_KEY" ] && echo set` and `grep -cq '^ABLO_API_KEY=' .env.local && echo wired` — never `cat .env.local`, never `echo $ABLO_API_KEY`. If neither check passes, ask the HUMAN to run `npx ablo login` once — it opens a browser and saves a `sk_test_` key locally; an agent must NOT run it. You never copy the key by hand: the next step writes it into `.env.local` (and gitignores it) for you.
|
|
14
14
|
|
|
15
|
-
Then PUSH — this is the step everything depends on. The server keeps its OWN copy of the schema. Run `npx ablo push
|
|
15
|
+
Then PUSH — this is the step everything depends on. The server keeps its OWN copy of the schema. Run `npx ablo push`: it pushes `ablo/schema.ts` (sandbox) AND writes `ABLO_API_KEY` into `.env.local` from the stored login. Until the schema is pushed, EVERY write to a new or changed model fails with `server_execute_unknown_model`. Re-run it after schema changes. `push` is one-shot; `dev` is the watcher, so use `npx ablo dev --no-watch` only when you intentionally want the dev command to push once and exit.
|
|
16
16
|
|
|
17
17
|
## Projects (one org, many apps)
|
|
18
18
|
|
|
@@ -29,7 +29,6 @@ TYPES: the project registers its schema ONCE via declaration merging — `npx ab
|
|
|
29
29
|
|
|
30
30
|
const schema = defineSchema({
|
|
31
31
|
weatherReports: model({
|
|
32
|
-
id: z.string(),
|
|
33
32
|
location: z.string(),
|
|
34
33
|
status: z.enum(['pending', 'ready']),
|
|
35
34
|
forecast: z.string().optional(),
|
|
@@ -190,6 +189,6 @@ Do not teach `/api`, `/agent`, `/ai-sdk`, `/core`, `/realtime`, or internal subp
|
|
|
190
189
|
- `npx ablo init --yes` (flags: `--framework`, `--auth`, `--storage direct|endpoint` (default `direct`), `--no-agent`, `--no-pull`, `--no-install`, `--no-login`). Generates `ablo/schema.ts` + the client; `--storage direct` (default) wires `databaseUrl`, `--storage endpoint` scaffolds the `ablo/data-source.ts` endpoint above instead.
|
|
191
190
|
- Key: see "Start here" — env → `.env.local` → ask the human to `npx ablo login`; never run `login` yourself, never copy keys by hand (`ablo push` writes `.env.local`).
|
|
192
191
|
- Adopt an existing DB: `npx ablo pull prisma [path]` / `npx ablo pull drizzle <module>`.
|
|
193
|
-
- `npx ablo push
|
|
192
|
+
- `npx ablo push` pushes the schema (sandbox) AND writes `ABLO_API_KEY` to `.env.local`; `npx ablo dev --no-watch` is the push-once form of the watcher; `npx ablo logs --no-follow` exits instead of tailing forever; `npx ablo mode sandbox|production` always needs the argument. `npx ablo push`/`status`/`pull`/`check`/`generate` are one-shot.
|
|
194
193
|
|
|
195
194
|
Canonical docs to read before integrating: `quickstart`, `schema-contract`, `integration-guide`, `guarantees`, `client-behavior`, `data-sources`, `examples/existing-python-backend`, `api`, `examples/ai-sdk-tool`, and `examples/server-agent`. When upgrading an existing integration, read `migration` — every breaking change, what to change, and which version introduced it.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abloatai/ablo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "The Collaboration Layer For AI Agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -119,7 +119,6 @@
|
|
|
119
119
|
"examples",
|
|
120
120
|
"AGENTS.md",
|
|
121
121
|
"llms.txt",
|
|
122
|
-
"llms-full.txt",
|
|
123
122
|
"LICENSE",
|
|
124
123
|
"NOTICE",
|
|
125
124
|
"README.md",
|
|
@@ -131,9 +130,11 @@
|
|
|
131
130
|
"build:cli": "tsup --config tsup.cli.config.ts",
|
|
132
131
|
"typecheck:cli": "tsc -p tsconfig.cli.json",
|
|
133
132
|
"pack:check": "npm_config_cache=${TMPDIR:-/tmp}/ablo-npm-cache npm pack --dry-run",
|
|
133
|
+
"lint": "npm run lint:imports && npm run lint:errors && npm run lint:docs",
|
|
134
134
|
"lint:imports": "node scripts/check-js-extensions.mjs",
|
|
135
135
|
"generate:errors": "tsx scripts/generate-error-docs.mts",
|
|
136
136
|
"lint:errors": "tsx scripts/check-error-docs.mts",
|
|
137
|
+
"lint:docs": "node scripts/check-doc-drift.mjs",
|
|
137
138
|
"lint:pkg": "publint",
|
|
138
139
|
"prepublishOnly": "npm run build && npm run lint:pkg",
|
|
139
140
|
"check:dist": "node scripts/check-dist-fresh.mjs",
|
package/docs/mcp/claude-code.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Claude Code
|
|
2
|
-
|
|
3
|
-
## Install
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
claude mcp add --transport http ablo https://<your-app>/api/mcp
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
That's it — no token or header needed. The endpoint is public and serves
|
|
10
|
-
only docs, schema lint, and scaffolds. The next `/help` in Claude Code will
|
|
11
|
-
list the Ablo Sync tools.
|
|
12
|
-
|
|
13
|
-
## Verify
|
|
14
|
-
|
|
15
|
-
In Claude Code, run:
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
/mcp list
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
You should see `ablo` with the integration tools enumerated:
|
|
22
|
-
`search_ablo_docs`, `get_recipe`, `get_api_surface`, `validate_schema`,
|
|
23
|
-
`scaffold_app`.
|
|
24
|
-
|
|
25
|
-
## Removing
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
claude mcp remove ablo
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## More
|
|
32
|
-
|
|
33
|
-
- [MCP overview](/docs/mcp) — what the server exposes and how the transport works.
|
|
34
|
-
- [Cursor setup](/docs/mcp/cursor) — same URL, different UI.
|
|
35
|
-
- [Windsurf setup](/docs/mcp/windsurf) — same URL, different UI.
|
package/docs/mcp/cursor.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Cursor
|
|
2
|
-
|
|
3
|
-
## Install
|
|
4
|
-
|
|
5
|
-
Add the Ablo Sync MCP server to Cursor's `mcp.json`:
|
|
6
|
-
|
|
7
|
-
```json
|
|
8
|
-
{
|
|
9
|
-
"mcpServers": {
|
|
10
|
-
"ablo": {
|
|
11
|
-
"transport": "http",
|
|
12
|
-
"url": "https://<your-app>/api/mcp"
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
The file lives at `~/.cursor/mcp.json` on macOS / Linux. No auth header is
|
|
19
|
-
needed — the endpoint is public and serves only docs, schema lint, and
|
|
20
|
-
scaffolds.
|
|
21
|
-
|
|
22
|
-
Restart Cursor. The Ablo Sync tools appear under the MCP icon in the agent
|
|
23
|
-
panel.
|
|
24
|
-
|
|
25
|
-
## Verify
|
|
26
|
-
|
|
27
|
-
In Cursor's agent panel, open the MCP tools list. You should see the
|
|
28
|
-
Ablo Sync integration tools and their JSON schemas: `search_ablo_docs`,
|
|
29
|
-
`get_recipe`, `get_api_surface`, `validate_schema`, `scaffold_app`.
|
|
30
|
-
|
|
31
|
-
## More
|
|
32
|
-
|
|
33
|
-
- [MCP overview](/docs/mcp) — what the server exposes and how the transport works.
|
|
34
|
-
- [Claude Code setup](/docs/mcp/claude-code) — CLI install.
|
|
35
|
-
- [Windsurf setup](/docs/mcp/windsurf) — same JSON shape.
|
package/docs/mcp/windsurf.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Windsurf
|
|
2
|
-
|
|
3
|
-
## Install
|
|
4
|
-
|
|
5
|
-
Add the Ablo Sync MCP server to Windsurf's MCP config:
|
|
6
|
-
|
|
7
|
-
```json
|
|
8
|
-
{
|
|
9
|
-
"mcpServers": {
|
|
10
|
-
"ablo": {
|
|
11
|
-
"transport": "http",
|
|
12
|
-
"url": "https://<your-app>/api/mcp"
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
The config path differs by platform — Windsurf surfaces it in Settings →
|
|
19
|
-
Cascade → MCP. Restart Windsurf after saving. No auth header is needed —
|
|
20
|
-
the endpoint is public and serves only docs, schema lint, and scaffolds.
|
|
21
|
-
|
|
22
|
-
## Verify
|
|
23
|
-
|
|
24
|
-
Cascade's MCP panel lists every configured server with its tools. You
|
|
25
|
-
should see `ablo` with the integration tools enumerated:
|
|
26
|
-
`search_ablo_docs`, `get_recipe`, `get_api_surface`, `validate_schema`,
|
|
27
|
-
`scaffold_app`.
|
|
28
|
-
|
|
29
|
-
## More
|
|
30
|
-
|
|
31
|
-
- [MCP overview](/docs/mcp) — what the server exposes and how the transport works.
|
|
32
|
-
- [Claude Code setup](/docs/mcp/claude-code) — CLI install.
|
|
33
|
-
- [Cursor setup](/docs/mcp/cursor) — same JSON shape.
|
package/docs/roadmap.md
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# Roadmap
|
|
2
|
-
|
|
3
|
-
What is shipped, what is next, and what we will not build.
|
|
4
|
-
|
|
5
|
-
## Shipped
|
|
6
|
-
|
|
7
|
-
- **Models, claims, commits** — the core API.
|
|
8
|
-
- **Audit log** — a tamper-evident, hash-chained record of who did what,
|
|
9
|
-
per principal.
|
|
10
|
-
- **MCP transport** — HTTP server at `/api/mcp`.
|
|
11
|
-
- **TypeScript SDK** — `@abloatai/ablo`, with React bindings.
|
|
12
|
-
- **Dashboard** — keys, audit, metrics, allowed origins.
|
|
13
|
-
- **Schema migrations** — change a model's shape after it already has data.
|
|
14
|
-
Ablo plans the migration, tells you which changes are safe to auto-apply,
|
|
15
|
-
and backfills the rest; the server applies and activates a migration only
|
|
16
|
-
if it succeeds. `ablo generate` emits typed clients from a pushed schema.
|
|
17
|
-
- **Structured errors** — every error has a stable code and a request id,
|
|
18
|
-
and the same codes work whether you reach Ablo over HTTP, WebSocket, or MCP.
|
|
19
|
-
- **Sync groups** — clients automatically receive only the records they have
|
|
20
|
-
access to, based on relationships you declare in the schema.
|
|
21
|
-
- **Agent coordination** — when several agents work on the same model, they
|
|
22
|
-
take turns instead of overwriting each other, via `intent(id)` handles
|
|
23
|
-
that claim, wait, and commit.
|
|
24
|
-
|
|
25
|
-
## In flight
|
|
26
|
-
|
|
27
|
-
- **Real-time presence** — see who else is viewing/editing a model
|
|
28
|
-
(coordination primitives landed; presence surface in progress).
|
|
29
|
-
- **Cross-instance fan-out via Redis** — pub/sub deltas at scale.
|
|
30
|
-
|
|
31
|
-
## On deck
|
|
32
|
-
|
|
33
|
-
- **Field-level subscriptions** — subscribe to one path, not the whole row.
|
|
34
|
-
- **Bulk import/export** — CSV/JSON round-trip with chain verification.
|
|
35
|
-
|
|
36
|
-
## Maybe, if demand
|
|
37
|
-
|
|
38
|
-
- **Python SDK** — when a customer is shipping a Python-only product.
|
|
39
|
-
- **Go SDK** — same.
|
|
40
|
-
- **Multi-region replication** — when latency requirements force it.
|
|
41
|
-
|
|
42
|
-
## We will not build
|
|
43
|
-
|
|
44
|
-
- **A general-purpose Postgres wrapper** — Ablo is for state with
|
|
45
|
-
concurrency semantics, not for storing every table.
|
|
46
|
-
- **Server-side compute** — no triggers, no stored procedures. Compute
|
|
47
|
-
belongs in your application code.
|
|
48
|
-
- **A document database UI** — your data lives in Ablo; the UI is your
|
|
49
|
-
product, not ours.
|
|
50
|
-
|
|
51
|
-
## How priorities shift
|
|
52
|
-
|
|
53
|
-
We move items between sections based on what customers ask for in
|
|
54
|
-
production. Filing a [feature request](/docs/contact) with a concrete use
|
|
55
|
-
case is more effective than a thread on Twitter.
|
package/docs/the-loop.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# The loop: how your data flows
|
|
2
|
-
|
|
3
|
-
This explainer moved to the canonical, maintained docs:
|
|
4
|
-
|
|
5
|
-
**→ https://abloatai.com/docs/webhooks**
|
|
6
|
-
|
|
7
|
-
The short version: Ablo has the same two-sided shape as Stripe — **you call Ablo to make changes (the client), and Ablo calls you to persist them (a signed webhook)** — plus realtime sync to every connected client.
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
your app ──write──▶ Ablo (hosted) ──realtime sync──▶ other clients
|
|
11
|
-
(the client) the transaction log (live, optimistic)
|
|
12
|
-
│
|
|
13
|
-
└──signed event──▶ /api/ablo/[...all] ──▶ YOUR database
|
|
14
|
-
(the webhook route)
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Ablo owns the ordered transaction log (the source of truth); your database is a
|
|
18
|
-
materialized copy you keep via the webhook. See the link above for the full
|
|
19
|
-
guide: scaffolding the handler (`ablo init`), local testing (`ablo dev`),
|
|
20
|
-
registering an endpoint (`ablo webhooks create`), signature verification, the
|
|
21
|
-
delivery/retry model, and best practices.
|