feat(api): policy and root CRUD endpoints

Policies and roots were editable only via SQL inside the container.
Full CRUD over both, validated against the vocabulary the policy
engine knows — unknown resolutions or sources answer 422 naming the
field, malformed JSON answers 422, deleting a referenced policy or an
occupied root answers 409. Closes #116 (API half).
This commit is contained in:
Miguel Palhas
2026-08-23 14:56:51 +01:00
parent 951669749b
commit 9fa1f0cc51
17 changed files with 1450 additions and 12 deletions
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE roots SET kind = ?, audience = ?, path = ?, policy_id = ?,\n updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 5
},
"nullable": []
},
"hash": "0a27365a669aa217ae7dae675ebf54c4e4a343c4b56c4a44eb56d1a26c2aea4b"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "INSERT INTO roots (kind, audience, path, policy_id) VALUES (?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "0ab0de146b1cc4689359d64b9bc2ca5b86e68b7529b7ff1440015b3c2e3cd975"
}
@@ -0,0 +1,20 @@
{
"db_name": "SQLite",
"query": "SELECT count(*) AS \"count!: i64\" FROM roots WHERE policy_id = ?",
"describe": {
"columns": [
{
"name": "count!: i64",
"ordinal": 0,
"type_info": "Integer"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "0b17cf3d6cc89efacd65d11d15ee6086f857f6c7efff660ae4a958a9f4ce033a"
}
@@ -0,0 +1,50 @@
{
"db_name": "SQLite",
"query": "SELECT r.id AS \"id!: i64\",\n r.kind AS \"kind!: String\",\n r.audience AS \"audience!: String\",\n r.path AS \"path!: String\",\n p.id AS \"policy_id!: i64\",\n p.name AS \"policy_name!: String\"\n FROM roots r JOIN policies p ON p.id = r.policy_id\n WHERE r.id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "kind!: String",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "audience!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "path!: String",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "policy_id!: i64",
"ordinal": 4,
"type_info": "Integer"
},
{
"name": "policy_name!: String",
"ordinal": 5,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false
]
},
"hash": "115eae1f44b4eed8ea9e75666f1a03b642654d2d99a23b4319bd018e7389cdff"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "INSERT INTO policies (\n name, required_audio, dub_blacklist, hdr_rules,\n size_bands, resolution_pref, source_weights, score_weights\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 8
},
"nullable": []
},
"hash": "20ba3c269b7dab2f6cc624ffec40c454f20b778878f13bba8e4ab261d43c7480"
}
@@ -0,0 +1,68 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\",\n name AS \"name!: String\",\n required_audio AS \"required_audio!: String\",\n dub_blacklist AS \"dub_blacklist!: String\",\n hdr_rules AS \"hdr_rules!: String\",\n size_bands AS \"size_bands!: String\",\n resolution_pref AS \"resolution_pref!: String\",\n source_weights AS \"source_weights!: String\",\n score_weights AS \"score_weights!: String\"\n FROM policies ORDER BY id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "name!: String",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "required_audio!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "dub_blacklist!: String",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "hdr_rules!: String",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "size_bands!: String",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "resolution_pref!: String",
"ordinal": 6,
"type_info": "Text"
},
{
"name": "source_weights!: String",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "score_weights!: String",
"ordinal": 8,
"type_info": "Text"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "3437ff6e5b0262e3a298d3883ef16583c0dd62e9a25e955866c3b8690489443e"
}
@@ -0,0 +1,20 @@
{
"db_name": "SQLite",
"query": "SELECT count(*) AS \"count!: i64\" FROM movies WHERE root_id = ?",
"describe": {
"columns": [
{
"name": "count!: i64",
"ordinal": 0,
"type_info": "Integer"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "4492267683b60d3104c3bf315cca56981adbecbb4722305cdad7241f4f0d8fec"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "DELETE FROM policies WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "5cc813fb311c8d582b97320b0bebd17ad32bc3611a5f9dc98944591d9a596f26"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE policies SET\n name = ?, required_audio = ?, dub_blacklist = ?, hdr_rules = ?,\n size_bands = ?, resolution_pref = ?, source_weights = ?,\n score_weights = ?,\n updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 9
},
"nullable": []
},
"hash": "61a350e4122f566b91d26b7195a0b625b86d84662f9d74ca3b65f60ac1661d61"
}
@@ -0,0 +1,62 @@
{
"db_name": "SQLite",
"query": "SELECT name AS \"name!: String\",\n required_audio AS \"required_audio!: String\",\n dub_blacklist AS \"dub_blacklist!: String\",\n hdr_rules AS \"hdr_rules!: String\",\n size_bands AS \"size_bands!: String\",\n resolution_pref AS \"resolution_pref!: String\",\n source_weights AS \"source_weights!: String\",\n score_weights AS \"score_weights!: String\"\n FROM policies WHERE id = ?",
"describe": {
"columns": [
{
"name": "name!: String",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "required_audio!: String",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "dub_blacklist!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "hdr_rules!: String",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "size_bands!: String",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "resolution_pref!: String",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "source_weights!: String",
"ordinal": 6,
"type_info": "Text"
},
{
"name": "score_weights!: String",
"ordinal": 7,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "6b34f7c8d536d505c166f5b9b5a4db5fa3008b08e8e173b5ca21f51cca1dd1ee"
}
@@ -0,0 +1,20 @@
{
"db_name": "SQLite",
"query": "SELECT count(*) AS \"count!: i64\" FROM series WHERE root_id = ?",
"describe": {
"columns": [
{
"name": "count!: i64",
"ordinal": 0,
"type_info": "Integer"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "cbaa326819ded9bf6e74654b4ef40e9247723f3ce10ca95114bb2bee849957a0"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "DELETE FROM roots WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "ec2c22c78df99b937819263742c5a1bd7dc57165d5353c2169210aafe2153a93"
}
@@ -0,0 +1,20 @@
{
"db_name": "SQLite",
"query": "SELECT id FROM policies WHERE id = ?",
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Integer"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "fd07d4f50079cc11154a6b1a605b315d3ce220f99dca9a727bb6e4b2eaa45edb"
}