File size: 2,795 Bytes
80a4a65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
04fc815
80a4a65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# db/ β€” Schema, seeds, and migration runner

This folder owns **everything database-related** for CyberArena:

```
db/
β”œβ”€β”€ schema/   ← numbered, idempotent SQL migrations (run in order)
β”œβ”€β”€ seed/     ← per-type example JSON (the real seeds live in app/generators/)
β”œβ”€β”€ apply.py  ← run every schema/*.sql against Supabase
└── README.md (this file)
```

## Schema files

Numbered with a 3-digit prefix so a directory listing shows the run
order:

```
000_extensions.sql                              β€” pgcrypto
001_users.sql                                   β€” users + leaderboard view
002_encryption_challenges.sql                   β€” crypto (red+blue)
003_(removed)                                   β€” was web exploitation
004_code_fixing_challenges.sql                  β€” code-fixing (blue)
005_log_analysis_challenges.sql                 β€” log-analysis (blue) + storage bucket
006_vulnerability_hunter_challenges.sql         β€” vulnerability-hunter (blue)
007_onevone.sql                                 β€” 1v1 mode (4 tables + claim_win RPC)
008_certificates.sql                            β€” certificate table + RLS
009_user_completions.sql                        β€” per-category completion counter
```

Each file is **idempotent**:

  * `CREATE TABLE IF NOT EXISTS …`
  * `DROP POLICY IF EXISTS …` followed by `CREATE POLICY …`
  * `CREATE OR REPLACE FUNCTION …` for the one RPC

Re-running `db/apply.py` after the schema is already in place is a
no-op.

## Running the migrations

```bash
# Dry-run (list the files in order, do not run)
python db/apply.py --dry-run

# Apply to Supabase (requires SUPABASE_SERVICE_KEY in .env)
python db/apply.py
```

The script POSTs every file's contents to the
`/rest/v1/rpc/exec_sql` endpoint. If the `exec_sql` RPC is not yet
defined in your project, create it once via the Supabase SQL editor:

```sql
CREATE OR REPLACE FUNCTION public.exec_sql(query text)
  RETURNS void LANGUAGE plpgsql AS $$
BEGIN EXECUTE query; END $$;
GRANT EXECUTE ON FUNCTION public.exec_sql(text) TO service_role;
```

> The `service_role` key is required because DDL bypasses RLS.

## Seeds

The actual curated seeds (Tier 4 safety net in the AI fallback chain)
live in the Python generator modules under `app/generators/`. The
files in `db/seed/` are **templates** β€” one example per challenge
type that documents the JSON shape the corresponding Supabase table
expects. Use them as a starting point if you want to manually insert
a custom challenge.

## Checking live state

```bash
python scripts/check_state.py     # one-page health report
python scripts/seed_pools.py --check
```

`check_state.py` reports row counts for every challenge table, the
1v1 tables, certificates, and `user_completions` (per category).