feat(security): harden gateway boundaries and usage policies

Consolidate subscription usage policy enforcement, privacy-safe persistence, and gateway security hardening into one reviewable change.

Includes bounded HTTP and execution envelopes, header and protocol guards, DNS and relay validation, authentication and secret projection hardening, secure backup/install paths, and regression coverage.
This commit is contained in:
elky
2026-09-04 03:45:52 +08:00
parent ddcbeb3ae9
commit 579f2c7cc1
1019 changed files with 190437 additions and 26080 deletions
@@ -265,11 +265,11 @@ CREATE TABLE IF NOT EXISTS public.dimension_collectors (
CREATE TABLE IF NOT EXISTS public.gemini_file_mappings (
id character varying(36) NOT NULL,
file_name character varying(255) NOT NULL,
file_name character varying(512) NOT NULL,
key_id character varying(36) NOT NULL,
user_id character varying(36),
display_name character varying(255),
mime_type character varying(100),
display_name character varying(512),
mime_type character varying(255),
source_hash character varying(64),
created_at timestamp with time zone NOT NULL,
expires_at timestamp with time zone NOT NULL
@@ -305,6 +305,7 @@ CREATE TABLE IF NOT EXISTS public.global_models (
CREATE TABLE IF NOT EXISTS public.ldap_configs (
id integer NOT NULL,
singleton_key integer DEFAULT 1 NOT NULL,
server_url character varying(255) NOT NULL,
bind_dn text NOT NULL,
bind_password_encrypted text,
@@ -788,6 +789,7 @@ ALTER SEQUENCE public.proxy_node_events_id_seq OWNED BY public.proxy_node_events
CREATE TABLE IF NOT EXISTS public.proxy_nodes (
id character varying(36) NOT NULL,
tunnel_generation character varying(64) NOT NULL,
name character varying(100) NOT NULL,
ip character varying(512) NOT NULL,
port integer NOT NULL,
@@ -802,7 +804,7 @@ CREATE TABLE IF NOT EXISTS public.proxy_nodes (
is_manual boolean DEFAULT false NOT NULL,
proxy_url character varying(500),
proxy_username character varying(255),
proxy_password character varying(500),
proxy_password text,
created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
remote_config json,
@@ -1275,6 +1277,7 @@ CREATE TABLE IF NOT EXISTS public.usage_counter_deltas (
request_id character varying(128) NOT NULL,
kind character varying(64) NOT NULL,
target_id text NOT NULL,
target_tunnel_generation character varying(64),
request_count_delta bigint DEFAULT 0 NOT NULL,
total_requests_delta bigint DEFAULT 0 NOT NULL,
success_count_delta bigint DEFAULT 0 NOT NULL,
@@ -1361,6 +1364,7 @@ CREATE TABLE IF NOT EXISTS public.user_preferences (
CREATE TABLE IF NOT EXISTS public.user_sessions (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
security_version bigint DEFAULT 0 NOT NULL,
client_device_id character varying(128) NOT NULL,
device_label character varying(120),
device_type character varying(20) DEFAULT 'unknown'::character varying NOT NULL,
@@ -1406,6 +1410,7 @@ CREATE TABLE IF NOT EXISTS public.users (
feature_settings jsonb,
is_active boolean DEFAULT true NOT NULL,
is_deleted boolean DEFAULT false NOT NULL,
security_version bigint DEFAULT 0 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
last_login_at timestamp with time zone,
@@ -177,6 +177,36 @@ END $mig$;
--
-- Name: ldap_configs ldap_configs_singleton_key_check; Type: CHECK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.ldap_configs
ADD CONSTRAINT ldap_configs_singleton_key_check CHECK (singleton_key = 1);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: ldap_configs ldap_configs_singleton_key_key; Type: CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.ldap_configs
ADD CONSTRAINT ldap_configs_singleton_key_key UNIQUE (singleton_key);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: management_tokens management_tokens_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -101,6 +101,14 @@ CREATE INDEX IF NOT EXISTS idx_payment_orders_gateway_order_id ON public.payment
--
-- Name: uq_payment_orders_payment_method_gateway_order_id; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX IF NOT EXISTS uq_payment_orders_payment_method_gateway_order_id ON public.payment_orders USING btree (payment_method, gateway_order_id);
--
-- Name: idx_payment_orders_kind_status; Type: INDEX; Schema: public; Owner: -
--
@@ -694,36 +694,6 @@ END $mig$;
--
-- Name: user_referrals user_referrals_inviter_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_referrals
ADD CONSTRAINT user_referrals_inviter_user_id_fkey FOREIGN KEY (inviter_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_referrals user_referrals_invitee_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_referrals
ADD CONSTRAINT user_referrals_invitee_user_id_fkey FOREIGN KEY (invitee_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_referrals user_referrals_first_paid_order_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -754,36 +724,6 @@ END $mig$;
--
-- Name: referral_rewards referral_rewards_inviter_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.referral_rewards
ADD CONSTRAINT referral_rewards_inviter_user_id_fkey FOREIGN KEY (inviter_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: referral_rewards referral_rewards_invitee_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.referral_rewards
ADD CONSTRAINT referral_rewards_invitee_user_id_fkey FOREIGN KEY (invitee_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: referral_rewards referral_rewards_source_order_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -145,6 +145,84 @@ CREATE INDEX IF NOT EXISTS ix_usage_settlement_snapshots_schema_version
CREATE INDEX IF NOT EXISTS ix_usage_settlement_snapshots_pricing_source
ON public.usage_settlement_snapshots USING btree (billing_pricing_source);
CREATE TABLE IF NOT EXISTS public.usage_cost_reservations (
request_id character varying(128) NOT NULL,
subject_id character varying(128) NOT NULL,
reservation_token character varying(128) NOT NULL,
admitted_at timestamp with time zone NOT NULL,
reserved_cost_units bigint NOT NULL,
actual_cost_units bigint,
state character varying(20) NOT NULL,
reservation_expires_at timestamp with time zone NOT NULL,
retain_until timestamp with time zone NOT NULL,
finalized_at timestamp with time zone,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT usage_cost_reservations_pkey PRIMARY KEY (reservation_token),
CONSTRAINT usage_cost_reservations_subject_id_fkey
FOREIGN KEY (subject_id)
REFERENCES public.users(id)
ON DELETE CASCADE,
CONSTRAINT usage_cost_reservations_state_check
CHECK (state IN ('reserved', 'finalized', 'released')),
CONSTRAINT usage_cost_reservations_reserved_cost_units_check
CHECK (reserved_cost_units >= 0),
CONSTRAINT usage_cost_reservations_actual_cost_units_check
CHECK (actual_cost_units IS NULL OR actual_cost_units >= 0),
CONSTRAINT usage_cost_reservations_expiry_check
CHECK (reservation_expires_at > admitted_at),
CONSTRAINT usage_cost_reservations_retention_check
CHECK (retain_until >= reservation_expires_at),
CONSTRAINT usage_cost_reservations_lifecycle_check CHECK (
(state = 'reserved' AND actual_cost_units IS NULL AND finalized_at IS NULL)
OR (state = 'finalized' AND actual_cost_units IS NOT NULL AND finalized_at IS NOT NULL)
OR (state = 'released' AND actual_cost_units IS NOT NULL
AND actual_cost_units = 0 AND finalized_at IS NOT NULL)
)
);
CREATE INDEX IF NOT EXISTS usage_cost_reservations_request_id_idx
ON public.usage_cost_reservations USING btree (request_id);
CREATE INDEX IF NOT EXISTS usage_cost_reservations_subject_admitted_at_idx
ON public.usage_cost_reservations USING btree (subject_id, admitted_at);
CREATE INDEX IF NOT EXISTS usage_cost_reservations_reservation_expires_at_idx
ON public.usage_cost_reservations USING btree (reservation_expires_at);
CREATE INDEX IF NOT EXISTS usage_cost_reservations_retain_until_token_idx
ON public.usage_cost_reservations USING btree (retain_until, reservation_token);
CREATE TABLE IF NOT EXISTS public.usage_request_admissions (
request_id character varying(128) NOT NULL,
subject_id character varying(128) NOT NULL,
event_token character varying(128) NOT NULL,
admitted_at timestamp with time zone NOT NULL,
retain_until timestamp with time zone NOT NULL,
state character varying(20) NOT NULL,
released_at timestamp with time zone,
created_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT usage_request_admissions_pkey PRIMARY KEY (event_token),
CONSTRAINT usage_request_admissions_subject_id_fkey
FOREIGN KEY (subject_id)
REFERENCES public.users(id)
ON DELETE CASCADE,
CONSTRAINT usage_request_admissions_retention_check
CHECK (retain_until > admitted_at),
CONSTRAINT usage_request_admissions_state_check
CHECK (state IN ('active', 'released')),
CONSTRAINT usage_request_admissions_lifecycle_check CHECK (
(state = 'active' AND released_at IS NULL)
OR (state = 'released' AND released_at IS NOT NULL AND released_at >= admitted_at)
)
);
CREATE INDEX IF NOT EXISTS usage_request_admissions_subject_admitted_at_idx
ON public.usage_request_admissions USING btree (subject_id, admitted_at);
CREATE INDEX IF NOT EXISTS usage_request_admissions_retain_until_token_idx
ON public.usage_request_admissions USING btree (retain_until, event_token);
CREATE INDEX IF NOT EXISTS idx_usage_settlement_dashboard_cover
ON public.usage_settlement_snapshots USING btree (request_id)
INCLUDE (