20260729_300_device_semantics.py 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. """Add governed device semantic codes, immutable versions, and reviews."""
  2. from alembic import op
  3. revision = "20260729_300"
  4. down_revision = "20260729_290"
  5. branch_labels = None
  6. depends_on = None
  7. def upgrade() -> None:
  8. op.execute(
  9. """
  10. CREATE TABLE public.device_semantic_codes (
  11. uid UUID PRIMARY KEY,
  12. ontology_uid UUID NOT NULL
  13. REFERENCES public.ontologies(uid) ON DELETE RESTRICT,
  14. code_type VARCHAR(20) NOT NULL
  15. CHECK (code_type IN ('fault','cause','action')),
  16. canonical_code VARCHAR(120) NOT NULL,
  17. canonical_name VARCHAR(300) NOT NULL,
  18. definition TEXT,
  19. status VARCHAR(20) NOT NULL DEFAULT 'draft'
  20. CHECK (
  21. status IN (
  22. 'draft','in_review','published','rejected','retired'
  23. )
  24. ),
  25. current_version INTEGER NOT NULL DEFAULT 1
  26. CHECK (current_version > 0),
  27. source_mappings JSONB NOT NULL DEFAULT '[]'::jsonb,
  28. evidence_uids JSONB NOT NULL DEFAULT '[]'::jsonb,
  29. suggestion_source VARCHAR(20) NOT NULL DEFAULT 'manual'
  30. CHECK (suggestion_source IN ('manual','rule','ai')),
  31. confidence DOUBLE PRECISION
  32. CHECK (
  33. confidence IS NULL
  34. OR (confidence >= 0 AND confidence <= 1)
  35. ),
  36. created_by VARCHAR(100),
  37. updated_by VARCHAR(100),
  38. created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  39. updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  40. UNIQUE (ontology_uid, code_type, canonical_code)
  41. );
  42. CREATE INDEX idx_device_semantic_codes_lookup
  43. ON public.device_semantic_codes(
  44. ontology_uid, code_type, status, canonical_code
  45. );
  46. CREATE INDEX idx_device_semantic_codes_updated
  47. ON public.device_semantic_codes(updated_at DESC);
  48. CREATE TABLE public.device_semantic_code_versions (
  49. uid UUID PRIMARY KEY,
  50. code_uid UUID NOT NULL
  51. REFERENCES public.device_semantic_codes(uid)
  52. ON DELETE CASCADE,
  53. version INTEGER NOT NULL CHECK (version > 0),
  54. snapshot JSONB NOT NULL,
  55. created_by VARCHAR(100),
  56. created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  57. UNIQUE (code_uid, version)
  58. );
  59. CREATE INDEX idx_device_semantic_code_versions_created
  60. ON public.device_semantic_code_versions(
  61. code_uid, created_at DESC
  62. );
  63. CREATE TABLE public.device_semantic_code_reviews (
  64. uid UUID PRIMARY KEY,
  65. code_uid UUID NOT NULL
  66. REFERENCES public.device_semantic_codes(uid)
  67. ON DELETE CASCADE,
  68. version INTEGER NOT NULL CHECK (version > 0),
  69. decision VARCHAR(20) NOT NULL
  70. CHECK (decision IN ('approve','reject')),
  71. reason VARCHAR(1000) NOT NULL DEFAULT '',
  72. actor_uid VARCHAR(100) NOT NULL,
  73. created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
  74. );
  75. CREATE INDEX idx_device_semantic_code_reviews_created
  76. ON public.device_semantic_code_reviews(
  77. code_uid, created_at DESC
  78. );
  79. """
  80. )
  81. def downgrade() -> None:
  82. # Governed code dictionaries and their approval evidence are retained.
  83. pass