Skip to content

Commit 35b6e40

Browse files
committed
fix: close review gaps in admin deployment
1 parent ac0c7f5 commit 35b6e40

4 files changed

Lines changed: 22 additions & 11 deletions

File tree

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ The suite rejects the production project, checks that the anon key belongs to th
5959

6060
GitHub runs staging only for `main` push or a main-branch manual dispatch, through the protected `staging` environment, after the credential-free build job passes. Set the repository variable `STAGING_E2E_ENABLED=true` only after the protected environment has the three secrets, current staging functions, schema, provider secret, dedicated unlimited-use test code, and a main-only deployment rule. A skipped staging job is not a pass.
6161

62-
The staging origin `http://127.0.0.1:18080` must be deployed in the CORS allowlists for `demo-code-login`, `ai`, `ai-stream`, and `announcements` before enabling the gate. Do not deploy those functions or apply migrations to an unverified project.
62+
The staging origin `http://127.0.0.1:18080` must be deployed in the CORS allowlists for `demo-code-login`, `ai`, `ai-stream`, `admin`, and `announcements` before enabling the gate. Do not deploy those functions or apply migrations to an unverified project.
6363

6464
## Working rules
6565

‎plans/release-checklist.md‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,18 @@ Run every step before merging this branch. Nothing here deploys anything; deploy
2222

2323
## 2. Migration review (before any deploy)
2424

25-
Two prepared migrations ship on this branch; neither is applied by the branch:
25+
The two Quality & Truth migrations below are recorded in section 0 as applied:
2626

2727
- `20260822000000_ai_request_cost_audit.sql` — audit columns on `ai_requests`
2828
- `20260822000001_source_provenance_metadata.sql` — `metadata` jsonb on `sources`
2929

30-
- [ ] Confirm both files reviewed against current schema, migration order, and RLS (`ai_requests` stays service-role-write-only; `sources` keeps per-user policies)
31-
- [ ] Apply order: migrations first, then edge functions (`ai`, `ai-stream`, `admin`), then frontend
30+
The audit follow-up adds one migration that must run before the updated `admin`
31+
function or frontend is deployed:
32+
33+
- `20260831191838_deactivate_announcements.sql` — adds `deactivated_at` and excludes deactivated announcements from authenticated reads without deleting dismissal history
34+
35+
- [ ] Confirm all changed migration files are reviewed against current schema, migration order, and RLS (`ai_requests` stays service-role-write-only; `sources` keeps per-user policies; announcement deactivation preserves dismissal rows)
36+
- [ ] Apply order: pending migrations first, then edge functions (`ai`, `ai-stream`, `admin`, `announcements` as changed), then frontend
3237
- both edge functions fall back to a base insert if audit columns are missing, so a deploy-order mistake degrades logging instead of breaking requests
3338
- the frontend sends `metadata` on source saves; deploying it before the `sources` migration will fail those writes
3439

‎supabase/functions/_shared/native-cors.test.ts‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ for (const functionName of browserCalledFunctions) {
2020
});
2121
}
2222

23-
Deno.test("announcements allows the isolated staging browser origin", async () => {
24-
const source = await Deno.readTextFile(new URL("../announcements/index.ts", import.meta.url));
25-
assertStringIncludes(source, '"http://127.0.0.1:18080"');
26-
});
23+
for (const functionName of ["admin", "announcements"]) {
24+
Deno.test(`${functionName} allows the isolated staging browser origin`, async () => {
25+
const source = await Deno.readTextFile(new URL(`../${functionName}/index.ts`, import.meta.url));
26+
assertStringIncludes(source, '"http://127.0.0.1:18080"');
27+
});
28+
}
2729

2830
Deno.test("native share links use the public HTTPS origin", async () => {
2931
const source = await Deno.readTextFile(new URL("../share/index.ts", import.meta.url));

‎supabase/functions/admin/index.ts‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const ALLOWED_ORIGINS = [
1212
"https://debate.pi-stack.org",
1313
"http://localhost:8080",
1414
"http://127.0.0.1:8080",
15+
"http://127.0.0.1:18080",
1516
"http://localhost:5173",
1617
"http://127.0.0.1:54321",
1718
"capacitor://localhost"
@@ -30,6 +31,9 @@ const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
3031
const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
3132
const supabase = createClient(supabaseUrl, supabaseServiceKey);
3233

34+
const ADMIN_ANNOUNCEMENT_COLUMNS =
35+
"id,title,body,target_type,target_user_ids,starts_at,expires_at,deactivated_at,created_by,created_at";
36+
3337
type UsageByUserRow = {
3438
user_id: string;
3539
email?: string | null;
@@ -158,7 +162,7 @@ Deno.serve(async (req) => {
158162
if (action === "announcements" && req.method === "GET") {
159163
const { data, error } = await supabase
160164
.from("admin_announcements")
161-
.select("id,title,body,target_type,target_user_ids,starts_at,expires_at,deactivated_at,created_by,created_at")
165+
.select(ADMIN_ANNOUNCEMENT_COLUMNS)
162166
.order("created_at", { ascending: false });
163167

164168
if (error) {
@@ -203,7 +207,7 @@ Deno.serve(async (req) => {
203207
expires_at: value.expiresAt,
204208
created_by: user.id,
205209
})
206-
.select("id,title,body,target_type,target_user_ids,starts_at,expires_at,deactivated_at,created_by,created_at")
210+
.select(ADMIN_ANNOUNCEMENT_COLUMNS)
207211
.single();
208212

209213
if (error) {
@@ -242,7 +246,7 @@ Deno.serve(async (req) => {
242246
.update({ deactivated_at: new Date().toISOString() })
243247
.eq("id", announcementId.value)
244248
.is("deactivated_at", null)
245-
.select("id,title,body,target_type,target_user_ids,starts_at,expires_at,deactivated_at,created_by,created_at")
249+
.select(ADMIN_ANNOUNCEMENT_COLUMNS)
246250
.maybeSingle();
247251

248252
if (error) {

0 commit comments

Comments
 (0)