Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions schema/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,20 @@ CREATE TABLE IF NOT EXISTS virtual_devices
);
CREATE UNIQUE INDEX IF NOT EXISTS virtual_devices_crop ON virtual_devices (crop_id);
CREATE INDEX IF NOT EXISTS virtual_devices_owner ON virtual_devices (owner_id);

-- Conexiones personales (clientes MCP y similares). Solo se guarda el SHA-256 del token; el prefijo visible permite
-- reconocerlo en la PWA. READ solo consulta; CONTROL además crea, edita y acciona. Revocar es borrar la fila.
CREATE TABLE IF NOT EXISTS access_tokens
(
id CHAR(24) PRIMARY KEY,
user_id CHAR(24) NOT NULL,
name TEXT NOT NULL,
token_hash TEXT NOT NULL,
prefix TEXT NOT NULL,
scope TEXT NOT NULL CHECK (scope IN ('READ', 'CONTROL')),
created_at TIMESTAMPTZ NOT NULL,
last_used_at TIMESTAMPTZ,
expires_at TIMESTAMPTZ
);
CREATE UNIQUE INDEX IF NOT EXISTS access_tokens_hash_key ON access_tokens (token_hash);
CREATE INDEX IF NOT EXISTS access_tokens_user ON access_tokens (user_id);
4 changes: 3 additions & 1 deletion tests/validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ done
fail=0
check() { if [ "$2" = "$3" ]; then echo "OK $1"; else echo "FAIL $1 (esperado $3, obtenido $2)"; fail=1; fi; }

check "diez tablas" "$(app "SELECT count(*) FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE'")" "10"
check "once tablas" "$(app "SELECT count(*) FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE'")" "11"
check "el alcance de una conexión se restringe" \
"$(app "INSERT INTO access_tokens (id,user_id,name,token_hash,prefix,scope,created_at) VALUES ('0000000000000000000000a1','u','x','h','spt_x','ADMIN',now())" 2>&1 >/dev/null | grep -qi 'check\|violates' && echo rechazado || echo aceptado)" "rechazado"
check "readings es una hipertabla de TimescaleDB" \
"$(app "SELECT count(*) FROM timescaledb_information.hypertables WHERE hypertable_name='readings'")" "1"
check "readings tiene política de retención" \
Expand Down
Loading