@abloatai/ablo 0.9.3 → 0.9.5

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/llms-full.txt CHANGED
@@ -142,10 +142,22 @@ This applies to any API-backed app: Python, Rails, Go, or Node. The backend keep
142
142
  its service layer and DB credentials. Ablo gets a Data Source endpoint and uses
143
143
  `ABLO_API_KEY`, not a database URL.
144
144
 
145
+ When the user DOES use the connection-string path (`Ablo({ databaseUrl })` /
146
+ `DATABASE_URL` at init): the role must be NON-superuser and NON-BYPASSRLS —
147
+ Ablo enforces row-level security and rejects owner roles with
148
+ `database_role_cannot_enforce_rls`. Neon's and Supabase's default dashboard
149
+ strings use the database OWNER (e.g. `neondb_owner`) and ARE rejected. EASIEST: have the user run `npx ablo migrate` — it detects the unsafe role and creates the scoped one automatically from their machine (owner credential never reaches Ablo; new DATABASE_URL written to the env file). Manual alternative — create a scoped role first (`CREATE ROLE ablo_app LOGIN PASSWORD '...'
150
+ NOSUPERUSER NOBYPASSRLS; GRANT CREATE, CONNECT ON DATABASE <db> TO ablo_app;
151
+ GRANT CREATE, USAGE ON SCHEMA public TO ablo_app;`), then swap user/password
152
+ into the same host/db string.
153
+
145
154
  ## Client Behavior
146
155
 
147
- Important options: `schema`, `apiKey`, `baseURL`, `persistence`, `fetch`,
148
- `defaultHeaders`, `defaultQuery`, `logger`, and `dangerouslyAllowBrowser`.
156
+ The options that matter: `schema` and `apiKey`. Everything else
157
+ (`persistence`, `logger`, transport tuning) has correct defaults — do NOT set
158
+ `baseURL`; the default already routes to the hosted API, and overriding it
159
+ breaks the connection. It exists only for self-hosted/proxy setups the human
160
+ explicitly asks for.
149
161
 
150
162
  There is intentionally no `databaseURL` option on `Ablo(...)`. Application and
151
163
  agent code use `ABLO_API_KEY`. Customer-owned app databases stay private behind
@@ -171,7 +183,7 @@ There are two sandbox surfaces:
171
183
  making real Ablo calls. It is agent-first: it should expose a prompt that can
172
184
  be pasted into Claude Code or Codex to wire one real model through Ablo.
173
185
  - Authenticated org sandboxes are real test environments. The default sandbox is
174
- the Stripe-style test mode for an org. It has an isolated sync group prefix,
186
+ the Stripe-style sandbox for an org. It has an isolated sync group prefix,
175
187
  can mint `sk_test_*` keys, and can be reset without touching live state.
176
188
 
177
189
  Additional org sandboxes can start blank or copy live configuration. Keep
@@ -190,8 +202,10 @@ Use these public environment names:
190
202
  - `ABLO_API_KEY` — SDK authentication for app and agent code. Where it comes
191
203
  from: the human runs `npx ablo login` once (browser; an agent must not run
192
204
  it), and `npx ablo dev` then writes `ABLO_API_KEY=sk_test_…` into
193
- `.env.local` automatically. Check the environment and `.env.local` before
194
- asking the human for a key.
205
+ `.env.local` automatically (and gitignores it). Check the environment and
206
+ `.env.local` for PRESENCE only (`grep -cq '^ABLO_API_KEY=' .env.local`)
207
+ before asking the human for a key — never print or echo the key value; a
208
+ secret in agent output lives in the conversation history forever.
195
209
 
196
210
  Do not ask customers to paste their app database URL into Ablo. If their app
197
211
  database is canonical, they expose a Data Source endpoint and keep database
package/llms.txt CHANGED
@@ -10,9 +10,9 @@ Use AI SDK for the agent loop. Use Ablo when agent reads and writes must persist
10
10
 
11
11
  First action when integrating into an app: run `npx ablo init --yes --framework <nextjs|vite|remix|vanilla> --storage datasource`. Agents have no TTY — `--yes` is REQUIRED or it HANGS. It scaffolds `ablo/schema.ts`, the client, the Data Source endpoint, and (for Next.js) the browser provider + session route, all on the current API. Edit the generated files rather than hand-writing from this doc.
12
12
 
13
- Second: make sure a key exists. Check `ABLO_API_KEY` in the environment, then `.env.local`. If neither has one, 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` for you.
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 dev --no-watch`: it pushes `ablo/schema.ts` (test mode) 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 (`npx ablo push` also works once the key is wired; bare `npx ablo dev` watches forever — don't, you have no TTY).
15
+ Then PUSH — this is the step everything depends on. The server keeps its OWN copy of the schema. Run `npx ablo dev --no-watch`: 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 (`npx ablo push` also works once the key is wired; bare `npx ablo dev` watches forever — don't, you have no TTY).
16
16
 
17
17
  ## Use this API
18
18
 
@@ -120,6 +120,8 @@ Do not add `databaseURL` to `Ablo(...)`. Application and agent code use `ABLO_AP
120
120
 
121
121
  Every schema model is backed by a database, and the default is YOUR OWN. Keep your rows in your Postgres and expose a Data Source endpoint that hands Ablo an ORM `adapter` (Drizzle is the default; Prisma and Kysely are also supported) — it owns the transaction, exactly-once idempotency, and outbox in ONE pass (no hand-written `commit`/`events`). Your `DATABASE_URL` lives in your app, never in `Ablo(...)`; run `npx ablo migrate` to provision the synced-model tables in your DB.
122
122
 
123
+ GOTCHA the user WILL hit: `DATABASE_URL` must use a NON-superuser, NON-BYPASSRLS role (Ablo enforces row-level security; owner roles are rejected with `database_role_cannot_enforce_rls`). Neon's and Supabase's default dashboard connection strings use the database OWNER (e.g. `neondb_owner`) and are rejected. EASIEST: `npx ablo migrate` detects the unsafe role and creates the scoped one automatically from the user's machine (owner credential never reaches Ablo; new DATABASE_URL written to the env file). Manual alternative — create a scoped role first: `CREATE ROLE ablo_app LOGIN PASSWORD '...' NOSUPERUSER NOBYPASSRLS; GRANT CREATE, CONNECT ON DATABASE <db> TO ablo_app; GRANT CREATE, USAGE ON SCHEMA public TO ablo_app;` — then swap user/password into the same host/db string.
124
+
123
125
  ```ts
124
126
  // app/api/ablo/source/route.ts
125
127
  import { dataSourceNext } from '@abloatai/ablo/source/next';
@@ -179,6 +181,6 @@ Do not teach `/api`, `/agent`, `/ai-sdk`, `/core`, `/realtime`, or internal subp
179
181
  - `npx ablo init --yes` (flags: `--framework`, `--auth`, `--storage`, `--no-agent`, `--no-pull`, `--no-install`, `--no-login`). Generates `ablo/schema.ts` + the `ablo/data-source.ts` endpoint above.
180
182
  - Key: see "Start here" — env → `.env.local` → ask the human to `npx ablo login`; never run `login` yourself, never copy keys by hand (`ablo dev` writes `.env.local`).
181
183
  - Adopt an existing DB: `npx ablo pull prisma [path]` / `npx ablo pull drizzle <module>`.
182
- - `npx ablo dev --no-watch` pushes the schema (test mode) AND writes `ABLO_API_KEY` to `.env.local` (default watches forever); `npx ablo logs --no-follow` (default tails forever); `npx ablo mode test|live` (always pass the arg). `npx ablo push`/`status`/`pull`/`check`/`generate` are one-shot.
184
+ - `npx ablo dev --no-watch` pushes the schema (sandbox) AND writes `ABLO_API_KEY` to `.env.local` (default watches forever); `npx ablo logs --no-follow` (default tails forever); `npx ablo mode sandbox|production` (always pass the arg). `npx ablo push`/`status`/`pull`/`check`/`generate` are one-shot.
183
185
 
184
186
  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`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/ablo",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "State control API for AI agents and collaborative apps.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -134,6 +134,7 @@
134
134
  "check:dist": "node scripts/check-dist-fresh.mjs",
135
135
  "pretest": "node scripts/check-dist-fresh.mjs",
136
136
  "test": "jest",
137
+ "test:quickstart": "node scripts/test-quickstart.mjs",
137
138
  "test:unit": "jest --testPathPattern=__tests__/unit",
138
139
  "test:integration": "jest --testPathPattern=__tests__/integration",
139
140
  "test:contract": "jest --testPathPattern=__tests__/contract",
@@ -183,10 +184,11 @@
183
184
  }
184
185
  },
185
186
  "dependencies": {
187
+ "jiti": "^2.7.0",
186
188
  "mobx": "^6.13.7",
187
189
  "mobx-react-lite": "^4.0.0",
188
- "zod": "^4.0.17",
189
- "uuid": "^11.1.0"
190
+ "uuid": "^11.1.0",
191
+ "zod": "^4.0.17"
190
192
  },
191
193
  "devDependencies": {
192
194
  "@ai-sdk/provider": "^3.0.0",