dev: add parallel dev environment under /docker/dev
Near-1:1 clone of the prod remote-access stack, isolated on a new external dev_edge network and fronted by the same shared Caddy instance (dual-homed on edge + dev_edge). Dev is manual-start (not on boot). - Hostnames: app-dev / api-dev .linumiq.net, tunnels under *.dev.linumiq.net, dev tunnel ingress on port 7001. - Dev Supabase (project supabase-dev, *-dev containers), web, frps, redis, stripe-stub, bandwidth-worker with fresh independent secrets (gitignored). - Shared Caddyfile: app-dev -> web-dev, api-dev -> dev kong (+webhook block), *.dev -> frps-dev vhost. Caddy compose dual-homed on dev_edge. - On-demand-TLS authorizer (prod check-subdomain, in gitignored volumes/) extended additively: app-dev/api-dev -> 200; *.dev delegated to the dev authorizer. Prod allow-list logic unchanged. - dev.sh manual up/down/ps helper; README documents topology + secrets. Secrets, frps.toml, volumes/, web worktree and data dirs are gitignored.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
-- 0002: pentest remediation (A4/W3 privilege reduction, A3 quota default, W1 subscription rows)
|
||||
BEGIN;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- A4 / W3: authenticated users must NOT be able to UPDATE tunnels directly.
|
||||
-- All legitimate writes (claim, token rotation, quota/usage, activation) go
|
||||
-- through service-role server routes / workers. A direct grant let an owner
|
||||
-- tamper with bytes_used, quota_bytes, is_active, token and subdomain.
|
||||
-- ---------------------------------------------------------------------------
|
||||
REVOKE UPDATE ON public.tunnels FROM authenticated;
|
||||
DROP POLICY IF EXISTS tunnels_update_own ON public.tunnels;
|
||||
-- SELECT (read-only dashboard) stays intact via tunnels_select_own.
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- A3: free-tier quota default 1 TiB -> 2 GiB, and shrink existing rows that
|
||||
-- still carry the old default so the kill-switch is meaningful.
|
||||
-- ---------------------------------------------------------------------------
|
||||
ALTER TABLE public.tunnels ALTER COLUMN quota_bytes SET DEFAULT 2147483648;
|
||||
UPDATE public.tunnels
|
||||
SET quota_bytes = 2147483648
|
||||
WHERE quota_bytes = 1099511627776;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- W1 (enablement): ensure every user has a subscriptions row so the billing
|
||||
-- webhook activation (PATCH by user) actually targets a row, and backfill
|
||||
-- existing users.
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE OR REPLACE FUNCTION public.handle_new_user()
|
||||
RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = public
|
||||
AS $$
|
||||
BEGIN
|
||||
INSERT INTO public.users_profile (user_id, email)
|
||||
VALUES (NEW.id, NEW.email)
|
||||
ON CONFLICT (user_id) DO NOTHING;
|
||||
|
||||
INSERT INTO public.subscriptions (user_id, plan, status)
|
||||
VALUES (NEW.id, 'free', 'active')
|
||||
ON CONFLICT (user_id) DO NOTHING;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
REVOKE ALL ON FUNCTION public.handle_new_user() FROM PUBLIC;
|
||||
GRANT EXECUTE ON FUNCTION public.handle_new_user() TO supabase_auth_admin;
|
||||
|
||||
INSERT INTO public.subscriptions (user_id, plan, status)
|
||||
SELECT id, 'free', 'active' FROM auth.users
|
||||
ON CONFLICT (user_id) DO NOTHING;
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user