docs: CLAUDE.md — OTM fork context + the first-party-app plan
Build / Build and release (push) Failing after 11s
Build / Build and release (push) Failing after 11s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014LCQmFvKshyAJsE8C3B5ET
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
# 13ft — OTM's fork
|
||||||
|
|
||||||
|
A self-hosted "read the article" fetcher (Python/Flask + gunicorn, ~200 lines
|
||||||
|
in `app/` (`portable.py` is the entrypoint)): it refetches a URL as Googlebot and serves the page
|
||||||
|
without the paywall/ad cruft. Forked 2026-10-14 from
|
||||||
|
[wasi-master/13ft](https://github.com/wasi-master/13ft) (the original project
|
||||||
|
was taken down once already — wasm-fyi → wasi-master — which is WHY we hold a
|
||||||
|
fork, not a dependency on GitHub/Docker Hub).
|
||||||
|
|
||||||
|
- **Remotes:** `gitea` = `tonym/13ft` on git.poweredbyotm.com (ours, push here);
|
||||||
|
`upstream` = GitHub wasi-master/13ft (pull only: `git fetch upstream && git
|
||||||
|
merge upstream/main`). Token for Gitea lives in `~/Projects/CLAUDE.md`.
|
||||||
|
- **Running today:** https://13ft.poweredbyotm.com on **anvil**, hand-provisioned
|
||||||
|
from the STOCK image `wasimaster/13ft:latest` (0.3.4) via
|
||||||
|
`platform/infra/13ft/setup-13ft-anvil.sh` (platform#91, closed) — a
|
||||||
|
`/srv/otm/clients/13ft/` compose stack + Caddy site with **basic auth**
|
||||||
|
(user `tony`; password root-only in `/srv/otm/clients/13ft/secrets/basic-auth.txt`).
|
||||||
|
Nothing in this repo is deployed yet.
|
||||||
|
|
||||||
|
## Where this is going (the reason for the fork)
|
||||||
|
|
||||||
|
Make it a proper **OTM first-party app** per
|
||||||
|
`platform/docs/first-party-app-guide.md` (house rules are CI-enforced by
|
||||||
|
`platform/test/first-party-house-rules.test.ts`):
|
||||||
|
|
||||||
|
1. **Build from this repo** — catalogue entry in
|
||||||
|
`platform/apps/otm-admin/lib/first-party-apps.ts` (`id: "13ft"`, repo
|
||||||
|
`tonym/13ft`, image `platform-13ft:latest`, port 5000, `hostname:
|
||||||
|
13ft.poweredbyotm.com`), then `build_app 13ft` / `deploy_app 13ft` via the
|
||||||
|
platform MCP. **First: destroy or rename the hand-provisioned `13ft` stack**
|
||||||
|
(same slug + hostname + container name) or the two will fight over the
|
||||||
|
Caddy site and the container name.
|
||||||
|
2. **Sign in with OTM** replaces Caddy basic auth: `needsAuthSecret` →
|
||||||
|
`OTM_SSO_SECRET`; add `/api/auth/otm-sso` (verify the HS256 ticket for aud
|
||||||
|
`app:13ft` — port `pickup/src/sso.js`, or in Python: HMAC-SHA256 over
|
||||||
|
`header.payload`, base64url, check `exp`/`aud`/`jti`, single-use) and a
|
||||||
|
session cookie; gate every fetch route on it. Grant-only (NOT
|
||||||
|
`publicAccess`) — a stranger's OTM account must not get a free fetch proxy.
|
||||||
|
3. **tides** (`needsAnalytics`) — the beacon `<script defer
|
||||||
|
src="${TIDES_HOST}/t.js" data-site="${TIDES_SITE_ID}">` in the page
|
||||||
|
template. **Ideas** (`needsSuggestions`) — a lightbulb that files Gitea
|
||||||
|
issues (see `pickup/src/ideas.js` for the plain-HTTP shape). Version +
|
||||||
|
`/changelog` + `/api/health` reporting the version + footer "Powered by OTM".
|
||||||
|
4. Keep the Dockerfile's non-root user (`thirteener`) and gunicorn; add a
|
||||||
|
`HEALTHCHECK`.
|
||||||
|
|
||||||
|
Until step 2 lands, basic auth stays — it is the whole gate.
|
||||||
|
|
||||||
|
## Dev
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python3 -m venv .venv && . .venv/bin/activate && pip install -r requirements.txt
|
||||||
|
cd app && python portable.py # http://127.0.0.1:5000 (the app lives in app/)
|
||||||
|
docker build -t 13ft-dev . && docker run --rm -p 5000:5000 13ft-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Upstream README (below in this repo's `README.md`) covers the rest. Keep
|
||||||
|
upstream's MIT license file.
|
||||||
Reference in New Issue
Block a user