feat: expand framework onboarding examples - #428
Conversation
A streaming chatbot container that answers questions about a private Postgres through a SQL tool run on read-only sessions. No API keys and no database credentials in the app: the AI binding routes through the gateway's ambient cloud identity, and the Postgres password resolves at runtime from the cloud secret store via postgres("db").connection().
Both alien packages stay serverExternalPackages — their native halves (napi addon, gateway binary) resolve with dynamic requires the bundler cannot see — and the per-platform prebuild packages are traced into the standalone output explicitly for the same reason. The image base is glibc because the bindings addon ships no musl prebuild.
The gateway forwards each model to its own upstream wire format rather than translating, so an OpenAI-compatible client reaches the OpenAI-protocol models only, and picking Claude in the model picker failed. Select the client from the model id, so every model the binding lists is usable through the one connection.
… route The container is publicly reachable, so an unauthenticated route that dropped and recreated the demo tables let anyone who found the URL reset them. Seed on the first question instead, creating and filling only what is missing, so there is no write endpoint to reach and a real table is never dropped. The model writes the SQL the tool runs, and read-only sessions stop writes but not a pg_sleep or a runaway scan holding a pool connection. Add a statement timeout and move the row cap into SQL, where a client-side slice still buffered every row the database returned. Register the template in the init fallback list so alien init ai-chatbot-ts still resolves when GitHub discovery is unavailable.
An answer is more convincing next to the rows it came from, so a drawer over the chat reads the demo tables through the same read-only pool the model's tool uses. Lifting that pool into app/db.ts keeps both readers on one connection with the same bounds. A native modal dialog carries the drawer: the top layer puts it above the background's full-viewport layers, and Escape, the backdrop, and focus containment come with it.
The runtime stage ran as root, so a compromised server held root inside the container; it now drops to the base image's node account. Seeding wrote its two inserts as separate autocommits, so a failure between them left customers with no orders, which the count check then read as already seeded. One transaction makes it all-or-nothing, and an advisory lock keeps concurrent replicas from racing on create-if-not-exists. Reads go through a shared helper that reseeds once on undefined_table, so a database emptied behind a running container recovers on the next request instead of failing until restart. Refs greptile review on #271
The session default was reversible from inside the statement it was meant to bound: `select set_config('default_transaction_read_only','off',false)` passes the single-SELECT check, and a later `WITH ... INSERT ... RETURNING` on the same pooled connection then writes. Reproduced against a real database, row written; a read-only transaction cannot be reopened for writing, and the same sequence now fails with `cannot execute ... in a read-only transaction`.
Refs greptile review on #271
The tool now takes a question name and a couple of enum filters, and app/queries.ts owns the statement each one runs with the model's arguments bound as parameters. Nothing the model sends reaches the database as SQL, so the session settings, the system catalogs, and the tables outside the demo schema are all out of reach by construction rather than by validation. The seed connection also gets a statement timeout, so a container that dies holding the advisory lock can no longer park every other seed.
`alien init` offers ai-quickstart-ts and ai-chatbot-ts, but neither appeared in the table, so the README undersold what the CLI can scaffold.
The trade-off was only stated in the README, which is not where someone reading the route or the stack definition will look for it.
Greptile SummaryAlien expands its onboarding catalog with customer-managed key and private-data chatbot examples while adjusting template discovery to list only directories with valid metadata.
Confidence Score: 3/5The PR is not yet safe to merge because template metadata failures still hide scaffoldable examples and the chatbot seed still leaves persistent databases with incomplete order data. Partial template metadata failures continue to return a successful but incomplete catalog, while the seed path checks only customer presence before skipping both datasets; both previously reported behaviors remain reachable on the current HEAD. Files Needing Attention: crates/alien-cli/src/commands/init.rs; examples/ai-chatbot-ts/app/seed.ts
|
| Filename | Overview |
|---|---|
| crates/alien-cli/src/commands/init.rs | Expands fallback metadata and changes template discovery to omit directories whose metadata cannot be fetched or parsed. |
| examples/ai-chatbot-ts/app/seed.ts | Creates and lazily seeds the chatbot's persistent customer and order demo tables. |
| examples/ai-chatbot-ts/app/api/chat/route.ts | Adds model selection, bounded database tooling, and streamed AI responses through the deployment binding. |
| examples/customer-keys-ts/src/vendor.ts | Implements the example's remote customer-key retrieval and tenant-scoped cryptographic operations. |
| examples/pnpm-workspace.yaml | Registers the new customer-focused examples in the examples workspace. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
Init["alien init"] --> Listing["Fetch examples directory"]
Listing --> Metadata["Fetch each template.toml"]
Metadata --> Catalog["Build selectable template catalog"]
Catalog --> Scaffold["Download and scaffold selected example"]
Chat["AI chatbot container"] --> Gateway["Ambient AI gateway"]
Chat --> Database["Private Postgres"]
Keys["Customer-keys example"] --> Vendor["Remote customer key service"]
Keys --> Ciphertext["Tenant-scoped encryption"]
Reviews (2): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile
| }; | ||
|
|
||
| templates.push(info); | ||
| if let Some(info) = info { |
There was a problem hiding this comment.
Partial metadata failures hide templates
When the directory listing succeeds but an individual template.toml request or parse fails, this branch silently omits that valid template while returning the remaining catalog as successful, causing it to disappear from interactive selection and explicit template-name matching instead of activating the fallback catalog.
Knowledge Base Used: Developer CLI and Deploy CLI
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/alien-cli/src/commands/init.rs
Line: 164-166
Comment:
**Partial metadata failures hide templates**
When the directory listing succeeds but an individual `template.toml` request or parse fails, this branch silently omits that valid template while returning the remaining catalog as successful, causing it to disappear from interactive selection and explicit template-name matching instead of activating the fallback catalog.
**Knowledge Base Used:** [Developer CLI and Deploy CLI](https://app.greptile.com/alien/-/custom-context/knowledge-base/alienplatform/alien/-/docs/developer-cli.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| const { rows } = await client.query("select count(*)::int as count from customers") | ||
| if (rows[0].count === 0) { | ||
| await client.query(CUSTOMERS) | ||
| await client.query(ORDERS) | ||
| } |
There was a problem hiding this comment.
Customer count masks incomplete seeds
If the persistent live database contains customers but its orders table is empty or partially populated, this single count check skips both seed inserts, leaving the order-related tools and data drawer with incomplete demo results until the database is manually reset.
Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/ai-chatbot-ts/app/seed.ts
Line: 76-80
Comment:
**Customer count masks incomplete seeds**
If the persistent live database contains customers but its orders table is empty or partially populated, this single count check skips both seed inserts, leaving the order-related tools and data drawer with incomplete demo results until the database is manually reset.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
What changed
Alien's onboarding examples now reflect the ways teams actually use the framework:
alien initso it skips invalid example directories and includes reliable fallback metadata.How to test
cargo check -p alien-cli@alienplatform/coreand@alienplatform/bindings.ALIEN-524