Sync with canonical matcha/phast@69bbbab and run on Fly as phast-app
The 2026-10-14 port took tea-mcp/src/phast, an older copy (light design, no OAuth). This merges matcha/phast main with its history: the black/orange phast.app and my.phast.app pages, and the Teahub-OAuth MCP server. On top, for prod: - server.py serves phast.app / and my.phast.app / from this repo (no copies), and /healthz - Dockerfile + start.sh: volume at /data, app runs unprivileged - fly.toml: phast-app, volume phast_data, GITEA_URL=https://teahub.xyz
This commit is contained in:
commit
cbd4a28e75
13 files changed
+612
-280
No files matched your search
@@ -1,42 +1,73 @@
|
||||
# Phast runtime
|
||||
# Phast app
|
||||
|
||||
This directory is the canonical source for the existing `phast-app` Fly app,
|
||||
serving `phast.app` and `my.phast.app`. It remains one Python/FastMCP runtime.
|
||||
Canonical source of truth for Phast app.
|
||||
|
||||
## App convention
|
||||
> **Connect your tools once. Bring your tool belt anywhere.**
|
||||
|
||||
`phast.json` is the minimal Prephab manifest. Schema version 1 requires a
|
||||
stable slug and name, an HTTPS origin, Python as the runtime, `/` as the default
|
||||
human route, `/mcp` as the default MCP route, and Prephab shape version 1.
|
||||
Registry tools return this same shape.
|
||||
Phast app gives a person one portable MCP plus a programmable Prefab home. Connect `my.phast.app/mcp` to an agent to create and manage Phast apps. A created Phast app has two matching surfaces:
|
||||
|
||||
`my.phast.app` renders its human surface with the installed Prefab UI package.
|
||||
Its MCP exposes `apps_list`, `apps_get`, `apps_create`, and `apps_update`, plus
|
||||
bounded status and Prefab-app tools. There is intentionally no delete.
|
||||
- `user.phast.app` — human / Prefab home
|
||||
- `user.phast.app/mcp` — the user's portable MCP tool belt
|
||||
|
||||
## Production blockers
|
||||
## V0 contract
|
||||
|
||||
The current Fly app has no volume and Phast has no accepted owner-auth pattern.
|
||||
The registry therefore refuses to treat the image filesystem as durable, and
|
||||
create/update always fail before writing. Do not deploy this as an enabled
|
||||
control plane until both seams are closed:
|
||||
`phast.json` is deliberately boring. It is mostly:
|
||||
|
||||
1. create and attach one Fly volume at `/data`, then set
|
||||
`PHAST_DATA_DIR=/data`; the runtime verifies that the directory is a mount;
|
||||
2. reuse an accepted FastMCP owner identity provider and replace the explicit
|
||||
mutation guard with caller identity/authorization checks.
|
||||
1. the MCP tool list and provider connections;
|
||||
2. references to delegated credential authority (Persimmons, never raw secrets);
|
||||
3. Prefab home/widget settings.
|
||||
|
||||
Do not substitute a shared secret in the UI or an environment flag for owner
|
||||
authentication. Once both prerequisites exist, exercise list/get/create/update
|
||||
through `my.phast.app/mcp`, verify persistence across a Machine replacement,
|
||||
then deploy through the existing Phast launch path.
|
||||
The browser and chat are two editors for the same declaration.
|
||||
|
||||
## Local validation
|
||||
### Browser flow
|
||||
|
||||
Run `python -m unittest tests.test_phast`. Tests use a temporary SQLite file;
|
||||
they do not weaken the production mount or authentication guards.
|
||||
Home → Edit Home → Add Widget → provider search → connect if necessary → place/configure widget.
|
||||
|
||||
## On Teahub prod (2026-10-14)
|
||||
Ported from the old factory (`tea-mcp/src/phast`, plus `phastacp` as `acp/`) as it was. Phast is a client of Teahub:
|
||||
this org owns the code, the site (`phast/site`) and phast.app. The Fly app named in `fly.toml` (`phast-app`) does not
|
||||
exist yet; the production blockers above still stand (volume at /data, owner auth via Gitea OAuth).
|
||||
### Agent flow
|
||||
|
||||
Connect once to `my.phast.app/mcp` → create/manage `user.phast.app` → search providers → add tools/widgets → stream/taste-test Prefab in chat → persist accepted UI to the same `phast.json`.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- **Phast app composes.** It owns the portable MCP/tool belt and Prefab composition.
|
||||
- **Oracle discovers.** Provider/MCP/OAuth discovery comes from the capability graph, not a hard-coded Phast app directory.
|
||||
- **Persimmons holds secrets.** Phast app stores connection/authority references, not secret values.
|
||||
- **Factory builds/operates.** Provisioning uses bounded deterministic infrastructure routes.
|
||||
- **Clients are replaceable.** ChatGPT, Claude, Codex, or another MCP client should be able to use the same Phast app without recollecting the user's tools.
|
||||
|
||||
V0 is intentionally not arbitrary app generation. Prove the portable-tool-belt + editable-home loop first.
|
||||
|
||||
## Naming and copy
|
||||
|
||||
Use **Phast app** when naming the product or one of its instances; use
|
||||
**Phast apps** for the plural. Write “your Phast app,” “create a Phast app,”
|
||||
and “My Phast app” for the management connector. Existing all-caps display
|
||||
styles may use “PHAST APP.” Apply this to page titles, metadata, navigation,
|
||||
buttons, examples, generated homes, MCP display text, and documentation.
|
||||
|
||||
Keep deliberate substitutions for “fast”: “make something phast,”
|
||||
“built phast,” and “make MCP apps phast.” Do not rename literal domains,
|
||||
URLs, `phast.json`, environment variables, CSS classes, tool names, or
|
||||
schema keys/values as part of a copy edit. Preserve user-chosen app names.
|
||||
|
||||
The public copy lives in `index.html` (phast.app), `my/index.html`
|
||||
(my.phast.app), and `server.py` (generated personal homes and MCP display
|
||||
text). `phast.json` supplies the management display name. Review these
|
||||
surfaces together when changing product naming.
|
||||
|
||||
Chair review: the standalone “PHAST.” wordmark and the “My Phast” connector
|
||||
label could be separate brand treatments. This change proposes “PHAST APP.”
|
||||
and “My Phast app” consistently; the chair should confirm those treatments.
|
||||
The phrase “your Phast” names an app instance, so it becomes “your Phast app.”
|
||||
|
||||
## Running
|
||||
|
||||
Prod since 2026-10-14: Fly app `phast-app` (this `fly.toml`), one machine, volume `phast_data` at `/data`
|
||||
(`PHAST_DATA_DIR=/data/phast`, `FASTMCP_HOME=/data/fastmcp`). It serves phast.app, my.phast.app and
|
||||
`*.phast.app`; the two pages are this repo's `index.html` and `my/index.html`, not copies. Sign-in is
|
||||
Teahub OAuth (app "Phast app" owned by `teahubxyz`, redirect `https://my.phast.app/auth/callback`);
|
||||
`GITEA_OAUTH_CLIENT_ID`, `GITEA_OAUTH_CLIENT_SECRET` and `JWT_SIGNING_KEY` exist only as Fly secrets.
|
||||
`ALLOWED_GITEA_USERS` says who may use it.
|
||||
|
||||
Deploy: `fly deploy --build-arg SOURCE_SHA=$(git rev-parse HEAD)`; `GET /healthz` reports the SHA.
|
||||
History before 2026-10-14 is `matcha/phast` from the old factory, merged in.
|
||||
Reference in new issue
Block a user