@consiliency/agent-board-schema 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -176,6 +176,10 @@
176
176
  {
177
177
  "id": "20260713000000_agent_board_rls_reassert_board_scoping",
178
178
  "sha256": "ba2c55bd11600d3dc86d54f02acd48ef4de711aaedce425e6bbfc85284a46c74"
179
+ },
180
+ {
181
+ "id": "20260714000200_agent_board_workload_providers_rls",
182
+ "sha256": "37a6f94d47b0948b1d5f384e52101eb48d9a15ba96a351669c87b907cc8a03e1"
179
183
  }
180
184
  ]
181
185
  }
@@ -0,0 +1,35 @@
1
+ -- Forward corrective migration (rollback Class B) — close the client-isolation
2
+ -- gap on agent_board.workload_providers.
3
+ --
4
+ -- WHY: 20260710000401 ships workload_providers with `grant select to
5
+ -- authenticated` but WITHOUT `enable row level security`. On an RLS-disabled
6
+ -- table a RESTRICTIVE policy never enforces, so the Portal b2 operator overlay
7
+ -- (`agent_board_b2_deny_client_jwt_select`, RESTRICTIVE) is INERT here — a
8
+ -- client-account JWT can read the entire provider registry. Its sibling tables
9
+ -- (nonfleet_sessions, nonfleet_invitations) enable RLS + a permissive read, so
10
+ -- the b2 deny works there; workload_providers was the odd one out.
11
+ --
12
+ -- Access model (confirmed with the canonical `grant select to authenticated`):
13
+ -- workload_providers is a GLOBAL registry keyed by issuer/audience (NOT
14
+ -- per-agent-owned), so it is fleet-readable (read predicate `true`); on adopters
15
+ -- carrying the b2 overlay, the RESTRICTIVE b2 deny then narrows client JWTs out.
16
+ -- This matches the Portal's chosen model (fleet-readable, client-denied) and its
17
+ -- operator hotfix (20260714000100), which retires once this canonical corrective
18
+ -- is adopted. Policy shape matches the Portal's deployed hotfix so retirement is
19
+ -- a clean no-op reassert.
20
+ --
21
+ -- Idempotent (drop-if-exists + create); only TIGHTENS/gates access (enabling RLS
22
+ -- with a permissive `true` read preserves authenticated read for adopters WITHOUT
23
+ -- b2, while making the b2 client-deny effective for those WITH it); no
24
+ -- schema-shape change; does NOT write schema_version. The canonical
25
+ -- `grant select to authenticated` (from 20260710000401) is preserved.
26
+
27
+ alter table agent_board.workload_providers enable row level security;
28
+
29
+ drop policy if exists workload_providers_deny_anon on agent_board.workload_providers;
30
+ create policy workload_providers_deny_anon on agent_board.workload_providers
31
+ as permissive for select to anon using (false);
32
+
33
+ drop policy if exists workload_providers_authenticated_read on agent_board.workload_providers;
34
+ create policy workload_providers_authenticated_read on agent_board.workload_providers
35
+ as permissive for select to authenticated using (true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@consiliency/agent-board-schema",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Canonical, immutable, exact-pinnable agent_board schema bundle: ordered SQL migrations, digest + compatibility manifest, and deterministic materialize/plan/check tooling for adopters.",
5
5
  "repository": "https://github.com/Consiliency/message-board.git",
6
6
  "type": "module",
@@ -2,7 +2,7 @@
2
2
  "schema": "agent_board_schema_manifest.v1",
3
3
  "interface": "IF-0-MBPLANE-BUNDLE-1",
4
4
  "package": "@consiliency/agent-board-schema",
5
- "packageVersion": "1.2.0",
5
+ "packageVersion": "1.3.0",
6
6
  "schemaVersion": 7,
7
7
  "minClientVersion": "1.1.0",
8
8
  "source": {
@@ -46,8 +46,8 @@
46
46
  "usage": "upsert (retention/monitoring defaults; on conflict do nothing)"
47
47
  }
48
48
  ],
49
- "migrationCount": 44,
50
- "aggregateSha256": "256b9de4e36809ed16778541adb8a573325b59dbcb30d56a428dbfd8fa5d2435",
49
+ "migrationCount": 45,
50
+ "aggregateSha256": "5acd6311c09a4134f4fb005e6b6f78a2a34665dfccc99e8e67e3bcb7b7325abb",
51
51
  "migrations": [
52
52
  {
53
53
  "order": 0,
@@ -444,6 +444,15 @@
444
444
  "sourceRef": "message-board",
445
445
  "bytes": 3464,
446
446
  "sha256": "ba2c55bd11600d3dc86d54f02acd48ef4de711aaedce425e6bbfc85284a46c74"
447
+ },
448
+ {
449
+ "order": 44,
450
+ "id": "20260714000200_agent_board_workload_providers_rls",
451
+ "filename": "20260714000200_agent_board_workload_providers_rls.sql",
452
+ "origin": "message-board-forward",
453
+ "sourceRef": "message-board",
454
+ "bytes": 2159,
455
+ "sha256": "37a6f94d47b0948b1d5f384e52101eb48d9a15ba96a351669c87b907cc8a03e1"
447
456
  }
448
457
  ],
449
458
  "excludedBridge": {
@@ -0,0 +1,40 @@
1
+ begin;
2
+ select plan(5);
3
+
4
+ -- After the corrective, workload_providers must have RLS ENABLED so a
5
+ -- RESTRICTIVE deny (the b2 client-JWT overlay on adopters that carry it) can
6
+ -- actually enforce — it is inert on an RLS-disabled table.
7
+
8
+ select ok(
9
+ (select relrowsecurity from pg_class c join pg_namespace n on n.oid=c.relnamespace
10
+ where n.nspname='agent_board' and c.relname='workload_providers'),
11
+ 'workload_providers has RLS enabled');
12
+
13
+ select is(
14
+ (select count(*)::int from pg_policy pol join pg_class c on c.oid=pol.polrelid
15
+ join pg_namespace n on n.oid=c.relnamespace
16
+ where n.nspname='agent_board' and c.relname='workload_providers'
17
+ and pol.polname='workload_providers_authenticated_read'),
18
+ 1, 'workload_providers_authenticated_read policy exists');
19
+
20
+ select is(
21
+ (select pg_get_expr(polqual, polrelid) from pg_policy pol join pg_class c on c.oid=pol.polrelid
22
+ join pg_namespace n on n.oid=c.relnamespace
23
+ where n.nspname='agent_board' and c.relname='workload_providers'
24
+ and pol.polname='workload_providers_authenticated_read'),
25
+ 'true', 'authenticated read predicate is true (global registry, fleet-readable)');
26
+
27
+ select is(
28
+ (select count(*)::int from pg_policy pol join pg_class c on c.oid=pol.polrelid
29
+ join pg_namespace n on n.oid=c.relnamespace
30
+ where n.nspname='agent_board' and c.relname='workload_providers'
31
+ and pol.polname='workload_providers_deny_anon'),
32
+ 1, 'workload_providers_deny_anon policy exists');
33
+
34
+ -- canonical fleet-read grant is preserved
35
+ select ok(
36
+ has_table_privilege('authenticated', 'agent_board.workload_providers', 'SELECT'),
37
+ 'authenticated retains SELECT grant on workload_providers');
38
+
39
+ select * from finish();
40
+ rollback;