| 1234567891011121314151617181920212223242526272829303132333435363738394041424344 |
- """Provision the private tenant only through the dedicated control identity."""
- from alembic import op
- revision = "20260817_511"
- down_revision = "20260817_510"
- branch_labels = None
- depends_on = None
- def upgrade() -> None:
- op.execute(r"""
- CREATE FUNCTION public.tenant_control_provision(p_payload jsonb)
- RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path=pg_catalog,public AS $tenant_provision$
- DECLARE v_tenant text; v_principal uuid; v_host text; v_key text; v_digest text;
- BEGIN
- IF NOT pg_has_role(session_user,'dataops_tenant_control','MEMBER') THEN RAISE EXCEPTION 'tenant_control_identity_required'; END IF;
- IF jsonb_typeof(p_payload)<>'object' OR NOT (p_payload ?& ARRAY['tenant_id','principal_id','host','idempotency_key']) OR p_payload-ARRAY['tenant_id','principal_id','host','idempotency_key']<>'{}'::jsonb THEN RAISE EXCEPTION 'tenant_payload_closed'; END IF;
- v_tenant:=p_payload->>'tenant_id'; v_host:=p_payload->>'host'; v_key:=p_payload->>'idempotency_key';
- IF v_tenant !~ '^[a-z][a-z0-9-]{0,62}$' OR coalesce(p_payload->>'principal_id','') !~* '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' OR v_host !~ '^[a-z0-9][a-z0-9.-]{0,252}$' OR v_host<>lower(v_host) OR v_key !~ '^[A-Za-z0-9._:-]{1,120}$' THEN RAISE EXCEPTION 'tenant_payload_invalid'; END IF;
- v_principal:=(p_payload->>'principal_id')::uuid; v_digest:=encode(sha256(convert_to(p_payload::text,'utf8')),'hex');
- INSERT INTO public.tenants(tenant_id,delivery_mode,state) VALUES(v_tenant,'private_single_tenant','active') ON CONFLICT(tenant_id) DO NOTHING;
- PERFORM set_config('dataops.tenant_id',v_tenant,true);
- INSERT INTO public.tenant_quotas(tenant_id,quota_name,limit_units) VALUES
- (v_tenant,'records',1),(v_tenant,'storage_objects',1),(v_tenant,'background_tasks',1),(v_tenant,'events',1),(v_tenant,'models',1),(v_tenant,'plugins',1),(v_tenant,'connectors',1),(v_tenant,'api_concurrency',1)
- ON CONFLICT(tenant_id,quota_name) DO NOTHING;
- INSERT INTO public.tenant_control_memberships(tenant_id,principal_id,host) VALUES(v_tenant,v_principal,v_host) ON CONFLICT(principal_id,host) DO UPDATE SET tenant_id=EXCLUDED.tenant_id;
- INSERT INTO public.tenant_audit_events(tenant_id,event_type,payload_digest,lease_fence) VALUES(v_tenant,'tenant.provision',v_digest,0);
- RETURN jsonb_build_object('tenant_id',v_tenant,'state','active','delivery_mode','private_single_tenant');
- END; $tenant_provision$;
- ALTER FUNCTION public.tenant_control_provision(jsonb) OWNER TO dataops_tenant_foundation_owner;
- REVOKE ALL ON FUNCTION public.tenant_control_provision(jsonb) FROM PUBLIC,dataops_app_runtime;
- GRANT EXECUTE ON FUNCTION public.tenant_control_provision(jsonb) TO dataops_tenant_control;
- """)
- def downgrade() -> None:
- op.execute("""
- DO $$ BEGIN
- IF EXISTS (SELECT 1 FROM public.tenants LIMIT 1) THEN RAISE EXCEPTION 'tenant provision downgrade refused while tenant data exists'; END IF;
- END $$;
- REVOKE EXECUTE ON FUNCTION public.tenant_control_provision(jsonb) FROM dataops_tenant_control;
- DROP FUNCTION public.tenant_control_provision(jsonb);
- """)
|