@team-semicolon/semicolony-cli 4.18.96 → 4.18.98
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.
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-- 195_worker_device_target_release.sql
|
|
2
|
+
--
|
|
3
|
+
-- Fix: /api/worker-fleet returns HTTP 500 for every role in production.
|
|
4
|
+
-- lib/worker-fleet/queries.ts DEVICE_ROWS_SQL selects
|
|
5
|
+
-- COALESCE(wd.active_release_id, p.active_release_id) AS target_release_id
|
|
6
|
+
-- but semo_ops.worker_devices has no active_release_id column — only
|
|
7
|
+
-- semo_ops.workspace_profiles does. The COALESCE already encodes the intended
|
|
8
|
+
-- contract (device-level override falls back to the profile default) and is
|
|
9
|
+
-- pinned by an existing contract test, so the fix is to add the missing
|
|
10
|
+
-- column, not to change the query.
|
|
11
|
+
--
|
|
12
|
+
-- Nullable is required: NULL means "no device-level override, use the
|
|
13
|
+
-- profile default", which is exactly what the COALESCE expects. No backfill.
|
|
14
|
+
--
|
|
15
|
+
-- Type/FK mirror semo_ops.workspace_profiles.active_release_id exactly
|
|
16
|
+
-- (uuid, nullable, FK -> semo_ops.worker_profile_releases(release_id)
|
|
17
|
+
-- ON DELETE SET NULL), verified against the live schema before writing this.
|
|
18
|
+
--
|
|
19
|
+
-- Grants: sc_fleet_board's existing SELECT on semo_ops.worker_devices is a
|
|
20
|
+
-- table-level grant (relacl 'sc_fleet_board=r'), which automatically covers
|
|
21
|
+
-- new columns — verified against pg_class.relacl before writing this. No
|
|
22
|
+
-- additional GRANT is needed for the fleet board read role.
|
|
23
|
+
--
|
|
24
|
+
-- Safety: additive only, single nullable column on one table.
|
|
25
|
+
-- The migration runner owns BEGIN/COMMIT; no transaction control here.
|
|
26
|
+
|
|
27
|
+
ALTER TABLE semo_ops.worker_devices
|
|
28
|
+
ADD COLUMN IF NOT EXISTS active_release_id UUID
|
|
29
|
+
REFERENCES semo_ops.worker_profile_releases(release_id) ON DELETE SET NULL;
|
|
30
|
+
|
|
31
|
+
COMMENT ON COLUMN semo_ops.worker_devices.active_release_id IS
|
|
32
|
+
'Device-level target release override. NULL means use the profile default (semo_ops.workspace_profiles.active_release_id) via COALESCE in DEVICE_ROWS_SQL.';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
-- 196_ops_control_room_board_grants.sql
|
|
2
|
+
--
|
|
3
|
+
-- SEMO Ops 컨트롤 룸(/ops)이 읽는 액션 아이템·온톨로지·지식베이스의 읽기 권한.
|
|
4
|
+
--
|
|
5
|
+
-- 배경: `feat(dashboard): unify SEMO Ops control room`(e906bf9c)이 액션 아이템과
|
|
6
|
+
-- Knowledge Fabric 카드를 추가하면서 워커 레지스트리와 같은 `fleetQuery`
|
|
7
|
+
-- (= sc_fleet_board 롤) 풀을 재사용했다. 그런데 174/175/180 이 부여한 것은
|
|
8
|
+
-- 워커 레지스트리와 크론 테이블뿐이라, 프로덕션 /ops 홈은 카드 두 개가
|
|
9
|
+
-- `permission denied for table action_items` / `... for table ontology` 로
|
|
10
|
+
-- 떴다. 즉 코드가 아니라 GRANT 가 빠진 릴리스 갭이다.
|
|
11
|
+
--
|
|
12
|
+
-- 원칙:
|
|
13
|
+
-- - 관측 전용이다. 세 테이블 모두 SELECT 만 준다 — 컨트롤 룸은 이 데이터를
|
|
14
|
+
-- 읽기만 하고, 쓰기 주체(sc_app·semo_ops_bot)와 컬럼이 겹치지 않아야 한다.
|
|
15
|
+
-- - knowledge_base 는 RLS 가 켜져 있다. GRANT 만 주면 정책 대상 롤이 아니라서
|
|
16
|
+
-- 에러 대신 0건이 조용히 나온다 — 그 실패 모드가 permission denied 보다 나쁘다.
|
|
17
|
+
-- 따라서 기존 SELECT 정책의 롤 목록에 sc_fleet_board 를 더한다. restricted
|
|
18
|
+
-- 분류 은닉 조건은 그대로 상속하므로 노출 범위는 sc_app 과 동일하다.
|
|
19
|
+
-- - 스키마는 174/175 와 같은 semo_ops (team_knowledge_fabric DB).
|
|
20
|
+
--
|
|
21
|
+
-- Safety: additive only. Runner가 BEGIN/COMMIT으로 감싸므로 트랜잭션 구문을 넣지 않는다.
|
|
22
|
+
|
|
23
|
+
GRANT SELECT ON TABLE semo_ops.action_items TO sc_fleet_board;
|
|
24
|
+
GRANT SELECT ON TABLE semo_ops.ontology TO sc_fleet_board;
|
|
25
|
+
GRANT SELECT ON TABLE semo_ops.knowledge_base TO sc_fleet_board;
|
|
26
|
+
|
|
27
|
+
-- knowledge_base 의 SELECT 정책에 보드 롤을 추가한다.
|
|
28
|
+
-- 기존 롤 목록을 읽어 덧붙이는 방식이라, 정책이 이미 다른 마이그레이션으로
|
|
29
|
+
-- 확장돼 있어도 그 확장을 지우지 않는다. 재실행해도 중복되지 않는다.
|
|
30
|
+
DO $$
|
|
31
|
+
DECLARE
|
|
32
|
+
existing_roles text[];
|
|
33
|
+
BEGIN
|
|
34
|
+
SELECT roles::text[]
|
|
35
|
+
INTO existing_roles
|
|
36
|
+
FROM pg_policies
|
|
37
|
+
WHERE schemaname = 'semo_ops'
|
|
38
|
+
AND tablename = 'knowledge_base'
|
|
39
|
+
AND policyname = 'knowledge_base_hide_restricted';
|
|
40
|
+
|
|
41
|
+
IF existing_roles IS NULL THEN
|
|
42
|
+
RAISE NOTICE 'knowledge_base_hide_restricted 정책이 없어 롤 확장을 건너뜁니다.';
|
|
43
|
+
ELSIF 'sc_fleet_board' = ANY (existing_roles) THEN
|
|
44
|
+
RAISE NOTICE 'sc_fleet_board 는 이미 knowledge_base_hide_restricted 대상입니다.';
|
|
45
|
+
ELSE
|
|
46
|
+
EXECUTE format(
|
|
47
|
+
'ALTER POLICY knowledge_base_hide_restricted ON semo_ops.knowledge_base TO %s',
|
|
48
|
+
-- 'sc_fleet_board' 는 반드시 ::text 로 캐스팅한다. 캐스팅이 없으면 무타입
|
|
49
|
+
-- 리터럴이 배열로 해석돼 `malformed array literal` 로 실패한다.
|
|
50
|
+
(SELECT string_agg(quote_ident(role_name), ', ')
|
|
51
|
+
FROM unnest(existing_roles || 'sc_fleet_board'::text) AS role_name)
|
|
52
|
+
);
|
|
53
|
+
END IF;
|
|
54
|
+
END
|
|
55
|
+
$$;
|
package/migrations/README.md
CHANGED
|
@@ -26,6 +26,8 @@ SEMICOLONY CLI의 PostgreSQL 마이그레이션 파일들.
|
|
|
26
26
|
| `185_worker_agent_feedback_scope.sql` | Hermes Semi/Colony actor에 정확한 feedback 범위·귀속을 추가하고 기존 바인딩만 백필 |
|
|
27
27
|
| `186_worker_agent_decision_capture.sql` | operator 승인 reference와 actor-bound decision recorder를 추가하고 정확한 decision scope만 백필 |
|
|
28
28
|
| `187_worker_agent_decision_digest_repair.sql` | Phase 6 decision recorder를 extension schema와 무관한 PostgreSQL SHA-256 primitive로 교정 |
|
|
29
|
+
| `195_worker_device_target_release.sql` | `worker_devices.active_release_id` (nullable, FK) 추가 — `/api/worker-fleet` DEVICE_ROWS_SQL의 COALESCE 대상 컬럼 누락으로 발생한 500 수정 |
|
|
30
|
+
| `196_ops_control_room_board_grants.sql` | `sc_fleet_board` 에 `action_items`·`ontology`·`knowledge_base` SELECT 부여 + knowledge_base SELECT 정책 롤 확장 — /ops 홈의 `permission denied` 카드 수정 |
|
|
29
31
|
|
|
30
32
|
## 007: Flat Skill Naming
|
|
31
33
|
|