Skip to content

Prepare for a public release: identity out of the code, one-line install - #10

Merged
ralyodio merged 2 commits into
masterfrom
public-cleanup
Aug 19, 2026
Merged

ralyodio merged 2 commits into
masterfrom
public-cleanup

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Two changes, both prerequisites for making this repository public.

The blog identity is configuration now

The post template hardcoded one person: a byline, a site name, a Mastodon handle, a GitHub profile and an email address, plus two CrawlProof account ids (an analytics site id and an ad slot id).

In a public repository that is worse than untidy. A fresh checkout would publish somebody else's name on every post, and meter that install's pageviews and ad impressions into an account it inherited from the repository rather than chose.

Identity now comes from a config file, read from $BLOG_CONFIG, then <blog dir>/blog.config.json, then ~/.config/cli-tools/blog.json, with the environment able to override any scalar field. The defaults are empty and the empty case is a good one rather than a broken one: no byline, no identity links, and no third-party scripts at all — which is the only fully smolweb-valid output this template has ever been able to produce.

  • blog-post config prints which file was picked up and what it resolved to.
  • blog-post new says so on stderr when it renders a post with no byline, because a silent anonymous post is the failure worth catching.
  • blog.config.example.json is the starting point; blog.config.json is gitignored.

Verified byte for byte: rendering with the maintainer's config reproduces the previous template exactly.

Also drops two colleagues' GitHub handles from gh-prs usage examples, removes a personal dev URL from the feed plugin doc, and ignores the usual credential file shapes.

One-line install, and a cli-tools front door

Installing this meant knowing to clone to a particular path, run pnpm, then run a script deliberately not named link. Fine for the author, poor front door for a public repo.

curl -fsSL https://raw.githubusercontent.com/profullstack/cli-tools/master/install.sh | sh

And a dispatcher, which is mostly there so the set has one name to install by — moshcode decides a tool is present by looking for a binary, so cli-tools on PATH is what makes moshcode install cli-tools and /cli-tools … work:

cli-tools list                 what is here, and what is on PATH
cli-tools update               pull, reinstall, relink
cli-tools link [--force]       symlink into ~/.local/bin
cli-tools aliases --install    merge the pit aliases
cli-tools <command> [args…]    run any of the others

Three things it is careful about:

  • The installer adopts a checkout that already owns these command names rather than cloning a second copy whose links are all refused as not-ours, with no explanation of why nothing changed.
  • update refuses to move a dirty or diverged tree instead of discarding work.
  • aliases --install merges: a name you bound yourself is kept, and the collision is reported rather than silently repointed.

Adds a tools plugin (/tools:install, /tools:list) alongside the existing blog and domain ones.

A correction

These docs had inherited the claim that PATH executables are needed because the pit runs aliases through zsh -c. The README already notes that stopped being true — current moshcode runs $SHELL -ic, which does source rc files. The new code and docs give the weaker, still-sufficient reason: a file works from every caller without anything having been sourced first.

The aliases are thin on purpose and none shares a name with a command, since a shell function beats PATH and would shadow the file. Both invariants are tests now, not comments.

Checks

  • 114 tests pass (was 98), typecheck clean.
  • Installer verified end to end into a sandbox: clean install links all 8 commands, re-run is idempotent, the adopt-existing-checkout path works, and the alias merge was tested against a copy of a real aliases.json.

🤖 Generated with Claude Code

ralyodio and others added 2 commits August 19, 2026 13:11
The post template hardcoded one person: a byline, a site name, a Mastodon
handle, a GitHub profile and an email address. It also hardcoded two CrawlProof
account ids — an analytics site id and an ad slot id. None of that is a property
of the tool, and in a public repository all of it is worse than untidy: a fresh
checkout would publish somebody else's name on every post, and meter that
install's pageviews and ad impressions into an account it inherited from the
repository rather than chose.

So identity now comes from a config file, read from $BLOG_CONFIG, then
<blog dir>/blog.config.json, then ~/.config/cli-tools/blog.json, with the
environment able to override any scalar field. The defaults are empty and the
empty case is a good one rather than a broken one: no byline, no identity links,
and no third-party scripts at all — which is the only fully smolweb-valid
output the template has ever been able to produce.

`blog-post config` prints which file was picked up and what it resolved to, and
`new` says so on stderr when it renders a post with no byline, because a silent
anonymous post is the failure worth catching.

Also replaces two colleagues' GitHub handles in gh-prs usage examples with
placeholders, drops a personal dev URL from the feed plugin doc, and ignores
blog.config.json plus the usual credential file shapes.

Verified: rendering with the maintainer's config reproduces the previous
template byte for byte. 98 tests pass, typecheck clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Until now installing these meant knowing to clone the repo to a particular
path, run pnpm, and then run a script whose name is not `link` for a reason
nobody would guess. That is fine for the person who wrote it and a poor front
door for a public repository.

So there is now `install.sh` behind the usual one-liner, and a `cli-tools`
command that fronts the set:

  cli-tools list                 what is here, and what is on PATH
  cli-tools update               pull, reinstall, relink
  cli-tools link [--force]       symlink into ~/.local/bin
  cli-tools aliases --install    merge the pit aliases
  cli-tools <command> [args…]    run any of the others

The dispatcher exists mainly so the set has one name to install by: moshcode
decides a tool is present by looking for a binary, so `cli-tools` on PATH is
what makes `moshcode install cli-tools` and `/cli-tools …` work.

Three things it is careful about. The installer adopts a checkout that already
owns these command names rather than cloning a second copy whose links are all
refused as not-ours, with no explanation of why nothing changed. `update`
refuses to move a dirty or diverged tree instead of discarding work. And
`aliases --install` merges: a name you bound yourself is kept, and the collision
is reported rather than silently repointed.

The aliases are thin on purpose and none shares a name with a command — a shell
function beats PATH, so an alias named after the file it wraps would shadow it.
Both invariants are now tests rather than comments.

Also adds a `tools` plugin (/tools:install, /tools:list) and corrects the
`zsh -c` rationale these docs had inherited: current moshcode runs `$SHELL -ic`,
which does source rc files. The reason to stay on PATH is the weaker one the
README already gives.

114 tests pass, typecheck clean, installer verified end to end into a sandbox.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

3 finding(s)

MEDIUM: 1 | LOW: 2

Severity Rule Location
MEDIUM redos-nested-quantifier src/domain-free.ts:56
LOW insecure-temp-file test/blog.test.ts:73
LOW insecure-temp-file test/blog.test.ts:74

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit b85f7c4 into master Aug 19, 2026
4 checks passed
@ralyodio
ralyodio deleted the public-cleanup branch August 19, 2026 13:20
ralyodio added a commit that referenced this pull request Sep 25, 2026
…er PR #10)

supabase.phonenumbers.bot gateway proxy; SUPABASE_SECRET_KEY as a secret
reference and SUPABASE_URL staged for the app change in
profullstack/phonenumbers.bot#10 (the app still derives its URL from
SUPABASE_DB_REF on master).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ralyodio added a commit that referenced this pull request Sep 26, 2026
* dev2: fleet kit to move Railway sites onto dev2 and deploy them on merge

dev2-site reads the truth from Railway (services, domains, volumes, database
variables), renders the box files from templates, provisions ~/www/<site> over
ssh, copies Postgres through Railway's ssh endpoint into the shared cluster,
issues the certificate over Porkbun DNS-01 before DNS moves, flips Porkbun,
stops and disconnects the Railway service, and merges the per-repo
deploy-dev2.yml. First site through it: bg0ne.com.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: README for the fleet kit

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: clone private repos over ssh with a read-only deploy key; show deploy stderr

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: write remote files via temp + mv

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: per-site self-hosted Supabase (stack, pull, load, storage, cutover) + proxied gateway hosts

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: README for the Supabase second pass and private repos

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: public verify waits out resolver caches

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site firewall: allow every Docker address pool on the data ports

With dozens of compose networks Docker moves to 192.168.x/20 pools, which an
allowlist of 172.16.0.0/12 alone drops (CONNECT_TIMEOUT to :5432 from the app).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: https clone for public repos; deploy key only when private

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: quote BUILD_SERVICES; sslmode=no-verify for node-postgres apps

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site verify: fail on connection failures in recent logs

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site vhost: large_client_header_buffers at server level

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site supabase-cutover: tolerate projects without pg_cron; no-verify db url

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: reload PostgREST schema cache after load; world-readable checkouts

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: sslmode=require&uselibpqcompat=true, the form both Bun.SQL and node-postgres accept

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: explicit 10.200.<n>.0/24 subnet per site (Docker pools exhausted)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: sslmode per driver (no-verify for node-postgres repos, require otherwise)

Bun.SQL forwards unknown URL parameters to the server as GUCs, so
uselibpqcompat=true was FATAL there while the health check stayed green.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: public build-time variables reach the build; nixpacks on Node 22

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* deploy-app.sh: export public build vars by parsing app.env, not sourcing it

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* deploy-app.sh: recreate the stack when the network subnet changes (stale embedded DNS)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site verify: require the vhost to exist

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: media2markdown.com repo override

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* deploy-app.sh: recreate the stack when a sibling service name fails to resolve

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: db copy from plain postgres images; DNS self-check parses services only; opensocial.chat override

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site scaffold: pass NIXPACKS_NODE_VERSION through --env, rewrite nodejs_18, --regen

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site scaffold: honour RAILWAY_DOCKERFILE_PATH and RAILPACK_*/NIXPACKS_* command variables

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site scaffold: pin corepack 0.36 in nixpacks Dockerfiles

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site cert: remove Railway's _acme-challenge CNAMEs before DNS-01

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: meshhook.com on Node 24

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: image-only sites (stock image + Railway start command, no clone/build); openaccess + openmcp overrides

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: mynaposter.com with its API companion on api.mynaposter.com

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site scaffold: per-site start_command feeds nixpacks; mynaposter commands

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* deploy-app.sh: REPO optional for image-only sites

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: a wildcard covers its one-label subdomains in the certificate order

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site cert: reuse a certificate issued in the last day

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: README for firewall, box-tune, image-only sites, companion ports

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: db-create for Turso/Supabase second passes; Turso variables re-pointed once a database exists

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: DEV2_JUMP / DEV2_PROBE for when the provider blocks this box

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site volumes: per-file, resumable, chunked copy (Railway's ssh drops long streams)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: keep credentials out of sites.d, which is committed and public

The fleet kit wrote the values it re-points straight into
`sites.d/<site>.json`, so this pull request carried threatcrush.com's
Supabase service_role key, its anon key and its database password, plus
tipoffwatch.com's retired Railway Postgres URL -- in a public repository.
ThreatCrush was right to fail the branch.

`env_overrides` now takes `secret:<KEY>`, resolved at render time from
~/.config/cli-tools/credentials.json (0600, outside every checkout) under
`<site>.<KEY>`, falling back to a bare `<KEY>` for a value shared across
sites. A reference with nothing behind it stops provision and names the
key, rather than deploying a site whose environment contains the literal
string `secret:...`.

`supabase-cutover` was the thing writing them, so it now writes the
reference and puts the value in credentials.json. It marks what is secret
by provenance -- the state keys it substituted -- with a key-name pattern
as the backstop, because a wrong guess there costs one extra entry in
credentials.json and the opposite costs a published key.

Also:
  - the four values above moved into credentials.json on dev1; provision
    renders exactly what it rendered before (verified by resolving each
    reference back to the value this commit removes)
  - `porkbun_keys` and the Supabase SMTP lookup hand-rolled this same
    read twice; both now call `cred()`
  - `db_name_for` validates the identifier at the one place it is
    derived: `db_name` in sites.d reaches `create database` and a DSN
    unquoted
  - drop the committed `__pycache__/*.pyc` and ignore it

The keys this branch published still need rotating; removing them here
does not unpublish them.

* dev2-site provision: inside port from the Dockerfile HEALTHCHECK/EXPOSE when Railway set none

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site deploy: default to the default branch once the scaffold PR is merged

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site verify: probe wildcards through a sample label

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: HTTP-01 certificates and manual DNS for zones not at Porkbun

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: nixpacks images get the start command as one bash -c string

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: app.moshcode.sh runs the pwa server, not the CLI

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: env_remove for settings a ported app refuses; README for the Turso second pass

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site db: copy the database the app's URL names, not the instance default

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site db: companions' variables may name the database

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: a published companion listens on its own inside port

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: tronbrowser.dev on Postgres, retire the Turso settings

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: app.moshcode.sh uses its own Dockerfile

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site cert: drop stale _acme-challenge TXT records before issuing

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: feedback.profullstack.com off Turso onto the shared Postgres cluster

Retire TURSO_DATABASE_URL and TURSO_AUTH_TOKEN, deploy master, and pin
sslmode=require for the @profullstack/libsql-pg pool (no-verify would connect
in the clear and pg_hba rejects that).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: reeleel.com registry on Postgres, retire the Turso replica settings

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: opensourcelegends.com off Turso onto the shared Postgres cluster

Retire TURSO_DATABASE_URL and TURSO_AUTH_TOKEN, deploy master, and pin
sslmode=require for the @profullstack/libsql-pg pool.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: detect the Postgres driver on origin's default branch; libsql-pg apps take sslmode=require

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: fall back to the live app.env on dev2 when Railway has no variables; box-tune raises inotify limits

Retiring a Railway service deletes its variables, and the Supabase second pass
re-renders app.env from them; a cutover after retire would have deployed an
empty environment. Envoy in a new stack segfaults once 128 inotify instances
are taken (about 130 containers).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site supabase-load --reset: replace an earlier load with a fresh dump

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: sites.d skip flag; community gardens stays on Railway

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site cert: reuse a fresh certificate only when it covers every name

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: ugig.net onto its own self-hosted Supabase stack

Gateway supabase.ugig.net -> :8249; the app's URL, anon/service keys and db
password re-pointed (keys as secret: references, values in credentials.json).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: sh1pt.com off Supabase cloud onto its own self-hosted stack

supabase.sh1pt.com gateway proxy, NEXT_PUBLIC_SUPABASE_URL re-pointed, keys as
secret references (the app carries sb_publishable/sb_secret keys the cutover
cannot match by value).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: smshub.dev off Supabase cloud onto its own self-hosted stack

supabase.smshub.dev gateway proxy, NEXT_PUBLIC_SUPABASE_URL re-pointed, keys as
secret references.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: b1dz.com onto its own self-hosted Supabase stack

Gateway supabase.b1dz.com -> :8240; URL, publishable/secret keys and db
password re-pointed (keys as secret: references, values in credentials.json).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: keep api.smshub.dev as an alias of the smshub Supabase gateway

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: marksyncr.com off Supabase cloud onto its own self-hosted stack

supabase.marksyncr.com gateway proxy; NEXT_PUBLIC_SUPABASE_URL re-pointed,
SUPABASE_JWT_SECRET and the keys as secret references.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: qaaas.dev onto its own self-hosted Supabase stack

Gateway supabase.qaaas.dev -> :8266; both URLs, anon/service keys and db
password re-pointed (keys as secret: references, values in credentials.json).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: qrypt.chat onto its own self-hosted Supabase stack

Gateway supabase.qrypt.chat -> :8239; both URL pairs, anon/service keys,
JWT discovery URL and db password re-pointed (secrets as secret: references).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: icemap.app off Supabase cloud onto its own self-hosted stack

supabase.icemap.app gateway proxy; SUPABASE_URL re-pointed, the service key as
a secret reference; extensions: postgis so the stack step installs it (the
load's own extension loop never reaches it).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: d0rz.com off Supabase cloud onto its own self-hosted stack

supabase.d0rz.com gateway proxy; NEXT_PUBLIC_SUPABASE_URL and SUPABASE_URL
re-pointed, keys as secret references.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: saasrow.com self-hosted Supabase gateway (stack up, app NOT cut over)

The app's backend is 36 Edge Functions called at SUPABASE_URL; none are ported,
so the cutover was rolled back and the app stays on the cloud project. Only the
supabase.saasrow.com proxy entry is kept.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: postammo.com off Supabase cloud onto its own self-hosted stack

supabase.postammo.com gateway proxy; SUPABASE_URL and SUPABASE_JWT_JWKS_URL
re-pointed, the db password and service key as secret references.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: logicsrc.com onto its own self-hosted Supabase stack

Gateway supabase.logicsrc.com -> :8272; SUPABASE_URL, publishable/secret
keys and db password re-pointed (keys as secret: references).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: weedforcrypto.com off Supabase cloud onto its own self-hosted stack

supabase.weedforcrypto.com gateway proxy; NEXT_PUBLIC_SUPABASE_URL re-pointed,
the db password and all four key variables as secret references.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: infernetprotocol.com onto its own self-hosted Supabase stack

Gateway supabase.infernetprotocol.com -> :8227; both URLs, DATABASE_URL and
the publishable/secret keys re-pointed (secrets as secret: references).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: phonenumbers.bot self-hosted Supabase stack staged (cutover after PR #10)

supabase.phonenumbers.bot gateway proxy; SUPABASE_SECRET_KEY as a secret
reference and SUPABASE_URL staged for the app change in
profullstack/phonenumbers.bot#10 (the app still derives its URL from
SUPABASE_DB_REF on master).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: pairux.com onto its own self-hosted Supabase stack

Gateway supabase.pairux.com -> :8274; URL, publishable/secret keys, db
password and the LiveKit recording S3 endpoint/credentials re-pointed at the
stack's own S3 protocol (secrets as secret: references).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: installer.pairux.com onto pairux.com's self-hosted Supabase stack

Shares the cloud project with pairux.com, so it shares the dev2 stack too:
URL, publishable/secret keys and db password re-pointed at supabase.pairux.com
(secrets as secret: references).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: bl0ggers.com off Supabase cloud onto its own self-hosted stack

supabase.bl0ggers.com gateway proxy (the wildcard already routes it);
NEXT_PUBLIC_SUPABASE_URL and SUPABASE_URL re-pointed, the db password and the
three key variables as secret references.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: brisk.news onto its own self-hosted Supabase stack

Gateway supabase.brisk.news -> :8238; URL and publishable/secret keys
re-pointed (keys as secret: references). Loaded from a fresh dump with
supabase-load --reset right before the cutover.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* supabase-load/pull: count psql-prefixed errors, stop docker exec eating loop input, grant functions by signature

- load: 'psql -f /dev/stdin' prefixes messages with psql:/dev/stdin:N:, so the
  error counts were always 0; count and list them properly.
- load: the schemas/extensions/buckets loops read from fd 3 -- the docker exec -i
  in the body swallowed the rest of stdin, so only the first entry ran (PostGIS
  was never created for icemap).
- pull: function grants were emitted without 'function' and without the
  signature, so all of them failed; emit them from pg_proc with regprocedure,
  and revoke PUBLIC where the cloud had done so.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2: coinpayportal.com self-hosted Supabase gateway (stack up, app NOT cut over)

supabase.coinpayportal.com -> :8273. The load lost public.payments (3405 rows)
to a NOT VALID check constraint the dump re-creates as enforced, so the
cutover is on hold until supabase-load handles NOT VALID constraints.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site supabase: new-style keys, Edge Functions step, NOT VALID constraints, vault, S3 host, bucket limits

- cutover maps sb_publishable_/sb_secret_ keys onto the stack's anon/service
  JWTs (they were never re-pointed before), rewrites <ref>.storage.supabase.co
  and swaps in the stack's S3 protocol credentials, and refuses to run while
  the cloud project still has Edge Functions the stack lacks.
- new supabase-functions: ports supabase/functions/* from the checkout onto the
  stack's edge runtime, copies the cloud function secrets into
  volumes/functions/secrets.env (env_file on the functions service), probes one.
- pull dumps NOT VALID check/fk constraints; load drops them before COPY and
  re-adds them NOT VALID after (coinpayportal's payments table failed on one).
- pull dumps vault secrets, load recreates them; buckets keep file_size_limit
  and allowed_mime_types; storage FILE_SIZE_LIMIT raised to 5 GiB.
- cron commands get the cloud URL and API keys rewritten before scheduling;
  the cloud cron probe no longer parses cron.job when pg_cron is absent.
- transient auth.one_time_tokens / auth.scim_* excluded from the data dump.
- stack no longer chowns an existing site root to root (CI deploys broke).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* supabase-functions: re-point cloud URL/keys inside the copied function secrets

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* supabase-functions: the API only lists secret names; take values from the site variables

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* supabase-functions: fix name collision in the probe; sites.d function_secrets overlay

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* dev2-site: sites.d crons -> /etc/cron.d (coinpayportal's minute payment monitor was a Vercel cron)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: coinpayportal cut over to its dev2 Supabase; saasrow function secrets as vault refs

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: tsbb.dev off Turso (TSBB_DATABASE_AUTH_TOKEN retired)

* sites.d: app.logicsrc.com runs apps/pwa (start_command, /healthz) and leaves Turso

* sites.d: p0dcasters.com off Turso

* sites.d: app.moshcode.sh off Turso (DATABASE_AUTH_TOKEN retired)

* sites.d: outreachgraph.com off Turso (TURSO_AUTH_TOKEN retired)

* sites.d: advis0r.com off Turso (DATABASE_URL was the libsql:// URL; drop DATABASE_AUTH_TOKEN)

* dev2-site: a sites.d health_path overrides the one recorded in the state file

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: c0upons.com and bufferoverride.com off Turso (retired settings dropped; c0upons also loses the dead SQLITECLOUD_URL)

* sites.d: hqtui.com and moshcoding.com off Turso

* sites.d: aiornot.vote off Turso

* dev2-site backup-install: version dev2-pg-backup.sh; dump every per-site Supabase stack and mirror storage files

The backup job only knew the shared cluster. With the cloud projects deleted the
20 <slug>-supabase-db containers were the sole copy of their data. Now: each stack's
postgres database is dumped (4-hourly, or daily when large) and verified like the
cluster's, and volumes/storage is rsync-mirrored daily. The script and its cron file
live here as templates and are installed by .

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* sites.d: communitygardensasappleseeds.info off skip, moving to dev2

Anthony reversed the stay-on-Railway decision ("move it all off railway").
Zone is at Cloudflare with no token in the vault, so the cert is HTTP-01
after the apex and www A records are pointed at dev2 by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* dev2-site: a failing nginx -t no longer reloads; HTTP-01 challenge files world-readable (umask 022)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* sites.d: bittorrented.com (not a Railway site; Supabase stack only, app stays on the DO droplet)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* supabase-load: extensions into the extensions schema (cloud DDL says extensions.gin_trgm_ops); skip generated columns in the URL rewrite

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant