CREATE TYPE "public"."module_access_level" AS ENUM('NONE', 'READ', 'WRITE');--> statement-breakpoint
CREATE TABLE "user_module_access" (
	"user_id" uuid NOT NULL,
	"module" varchar(32) NOT NULL,
	"level" "module_access_level" DEFAULT 'NONE' NOT NULL,
	"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
	CONSTRAINT "user_module_access_user_id_module_pk" PRIMARY KEY("user_id","module")
);
--> statement-breakpoint
ALTER TABLE "user_module_access" ADD CONSTRAINT "user_module_access_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "user_module_access_user_id_idx" ON "user_module_access" USING btree ("user_id");--> statement-breakpoint
-- Backfill: every account that existed before module entitlements were
-- introduced keeps everything it could already reach. Without this the new
-- ModuleAccessGuard would lock existing users out of their own data, because a
-- missing row means NONE.
--
-- Deliberately scoped to accounts present at migration time: accounts created
-- afterwards start with no modules and are granted explicitly in the admin
-- cockpit. Idempotent — re-running grants nothing twice and never downgrades a
-- level an administrator has since changed.
INSERT INTO "user_module_access" ("user_id", "module", "level")
SELECT u."id", m."module", 'WRITE'::"public"."module_access_level"
FROM "users" u
CROSS JOIN (
  VALUES ('trading'), ('portfolio'), ('market'), ('capital'), ('management'), ('community')
) AS m("module")
ON CONFLICT ("user_id", "module") DO NOTHING;