lorebase-store 0.2.3__py3-none-any.whl

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.
Files changed (163) hide show
  1. lorebase_store/__init__.py +1 -0
  2. lorebase_store/_migrations/env.py +106 -0
  3. lorebase_store/_migrations/script.py.mako +27 -0
  4. lorebase_store/_migrations/versions/0001_initial_schema.py +1071 -0
  5. lorebase_store/_migrations/versions/0002_merge_attempt_details.py +74 -0
  6. lorebase_store/_migrations/versions/0003_webhooks.py +127 -0
  7. lorebase_store/_migrations/versions/0004_defer_revision_references.py +38 -0
  8. lorebase_store/_migrations/versions/0005_security_definer_reads.py +396 -0
  9. lorebase_store/_migrations/versions/0006_api_key_usage.py +48 -0
  10. lorebase_store/_migrations/versions/0007_document_extraction.py +154 -0
  11. lorebase_store/_migrations/versions/0008_definer_argument_checks.py +178 -0
  12. lorebase_store/_migrations/versions/0009_api_key_networks.py +33 -0
  13. lorebase_store/_migrations/versions/0010_overlay_branches.py +582 -0
  14. lorebase_store/_migrations/versions/0011_branch_scoped_search_index.py +229 -0
  15. lorebase_store/_migrations/versions/0012_overlay_neighborhood_lookups.py +185 -0
  16. lorebase_store/_migrations/versions/0013_web_sessions.py +72 -0
  17. lorebase_store/_migrations/versions/0014_embedding_jobs.py +70 -0
  18. lorebase_store/_migrations/versions/0015_append_only_audit_log.py +83 -0
  19. lorebase_store/_migrations/versions/0016_sealed_webhook_keys.py +55 -0
  20. lorebase_store/_migrations/versions/0017_background_branch_copies.py +77 -0
  21. lorebase_store/_migrations/versions/0018_search_lexicon.py +477 -0
  22. lorebase_store/_migrations/versions/0019_vault_bindings.py +56 -0
  23. lorebase_store/_migrations/versions/0020_outbox_consumers.py +150 -0
  24. lorebase_store/_migrations/versions/0021_schema_suggestions.py +114 -0
  25. lorebase_store/_migrations/versions/0022_read_audit_and_shared_rate_limits.py +133 -0
  26. lorebase_store/_migrations/versions/0023_agent_trace.py +96 -0
  27. lorebase_store/_migrations/versions/0024_embedding_template_keys.py +205 -0
  28. lorebase_store/_migrations/versions/0025_snapshot_refs.py +35 -0
  29. lorebase_store/_migrations/versions/0026_plain_reverse_link_index.py +112 -0
  30. lorebase_store/_migrations/versions/0027_vault_rotation_and_tombstones.py +145 -0
  31. lorebase_store/_migrations/versions/0028_operation_deferred_events.py +71 -0
  32. lorebase_store/_migrations/versions/0029_agent_trace_sessions.py +108 -0
  33. lorebase_store/_migrations/versions/0030_path_fanout.py +31 -0
  34. lorebase_store/_migrations/versions/0031_branch_builds.py +91 -0
  35. lorebase_store/_migrations/versions/0032_lineage_revisions.py +35 -0
  36. lorebase_store/_migrations/versions/0033_vault_moved_tokens.py +30 -0
  37. lorebase_store/_migrations/versions/0034_inference_endpoint_modes.py +73 -0
  38. lorebase_store/_migrations/versions/0035_search_truncation.py +104 -0
  39. lorebase_store/_migrations/versions/0036_lineage_maps.py +325 -0
  40. lorebase_store/_migrations/versions/0037_bm25_search.py +346 -0
  41. lorebase_store/auth/__init__.py +52 -0
  42. lorebase_store/auth/api_keys.py +161 -0
  43. lorebase_store/auth/audit.py +382 -0
  44. lorebase_store/auth/checkpoints.py +185 -0
  45. lorebase_store/auth/grants.py +161 -0
  46. lorebase_store/auth/principals.py +158 -0
  47. lorebase_store/auth/scope.py +70 -0
  48. lorebase_store/auth/sessions.py +153 -0
  49. lorebase_store/auth/unit.py +53 -0
  50. lorebase_store/auth/usage.py +70 -0
  51. lorebase_store/blobs.py +73 -0
  52. lorebase_store/bm25.py +346 -0
  53. lorebase_store/bulk.py +147 -0
  54. lorebase_store/bundle.py +1830 -0
  55. lorebase_store/changefeed.py +261 -0
  56. lorebase_store/commit/__init__.py +42 -0
  57. lorebase_store/commit/changes.py +67 -0
  58. lorebase_store/commit/errors.py +60 -0
  59. lorebase_store/commit/migrations.py +335 -0
  60. lorebase_store/commit/pipeline.py +754 -0
  61. lorebase_store/commit/schema.py +123 -0
  62. lorebase_store/db.py +58 -0
  63. lorebase_store/definer.py +50 -0
  64. lorebase_store/digests.py +99 -0
  65. lorebase_store/embeddings.py +444 -0
  66. lorebase_store/endpoint_modes.py +59 -0
  67. lorebase_store/extraction/__init__.py +61 -0
  68. lorebase_store/extraction/items.py +187 -0
  69. lorebase_store/extraction/materialize.py +364 -0
  70. lorebase_store/extraction/proposal.py +65 -0
  71. lorebase_store/extraction/review.py +168 -0
  72. lorebase_store/gc.py +970 -0
  73. lorebase_store/indexes.py +1033 -0
  74. lorebase_store/jobs.py +651 -0
  75. lorebase_store/keyring.py +72 -0
  76. lorebase_store/layout.py +335 -0
  77. lorebase_store/materialize/__init__.py +103 -0
  78. lorebase_store/materialize/apply.py +436 -0
  79. lorebase_store/materialize/background.py +1184 -0
  80. lorebase_store/materialize/branch.py +268 -0
  81. lorebase_store/materialize/build.py +536 -0
  82. lorebase_store/materialize/derived.py +540 -0
  83. lorebase_store/materialize/lineage_backfill.py +502 -0
  84. lorebase_store/materialize/links.py +266 -0
  85. lorebase_store/materialize/overlay.py +292 -0
  86. lorebase_store/materialize/paths.py +315 -0
  87. lorebase_store/materialize/rebuild.py +326 -0
  88. lorebase_store/materialize/rows.py +153 -0
  89. lorebase_store/materialize/sensitivity.py +66 -0
  90. lorebase_store/materialize/snapshot.py +205 -0
  91. lorebase_store/materialize/stale.py +444 -0
  92. lorebase_store/materialize/verify.py +321 -0
  93. lorebase_store/merging/__init__.py +39 -0
  94. lorebase_store/merging/attempts.py +334 -0
  95. lorebase_store/merging/lineage.py +123 -0
  96. lorebase_store/merging/service.py +652 -0
  97. lorebase_store/migrations.py +133 -0
  98. lorebase_store/models/__init__.py +136 -0
  99. lorebase_store/models/base.py +64 -0
  100. lorebase_store/models/enums.py +132 -0
  101. lorebase_store/models/governance.py +268 -0
  102. lorebase_store/models/ingestion.py +288 -0
  103. lorebase_store/models/materialized.py +277 -0
  104. lorebase_store/models/proposals.py +195 -0
  105. lorebase_store/models/queues.py +87 -0
  106. lorebase_store/models/tracing.py +116 -0
  107. lorebase_store/models/versioning.py +222 -0
  108. lorebase_store/models/webhooks.py +96 -0
  109. lorebase_store/nodestore.py +384 -0
  110. lorebase_store/objectstore.py +162 -0
  111. lorebase_store/outbox_events.py +166 -0
  112. lorebase_store/profiling/__init__.py +58 -0
  113. lorebase_store/profiling/delimited.py +109 -0
  114. lorebase_store/profiling/postgres.py +211 -0
  115. lorebase_store/profiling/record_files.py +127 -0
  116. lorebase_store/profiling/records.py +92 -0
  117. lorebase_store/profiling/sql_databases.py +298 -0
  118. lorebase_store/ratelimit.py +129 -0
  119. lorebase_store/reads.py +1491 -0
  120. lorebase_store/replicas.py +434 -0
  121. lorebase_store/repositories/__init__.py +152 -0
  122. lorebase_store/repositories/changesets.py +59 -0
  123. lorebase_store/repositories/deferred_events.py +142 -0
  124. lorebase_store/repositories/documents.py +305 -0
  125. lorebase_store/repositories/domains.py +97 -0
  126. lorebase_store/repositories/events.py +205 -0
  127. lorebase_store/repositories/index_view.py +489 -0
  128. lorebase_store/repositories/invocations.py +68 -0
  129. lorebase_store/repositories/materializations.py +276 -0
  130. lorebase_store/repositories/materialized.py +1129 -0
  131. lorebase_store/repositories/merges.py +417 -0
  132. lorebase_store/repositories/proposal_items.py +199 -0
  133. lorebase_store/repositories/proposals.py +184 -0
  134. lorebase_store/repositories/provenance.py +77 -0
  135. lorebase_store/repositories/refs.py +452 -0
  136. lorebase_store/repositories/revisions.py +273 -0
  137. lorebase_store/repositories/scope.py +33 -0
  138. lorebase_store/repositories/source_runs.py +123 -0
  139. lorebase_store/repositories/suggestions.py +638 -0
  140. lorebase_store/runtime.py +87 -0
  141. lorebase_store/schema_cache.py +50 -0
  142. lorebase_store/settings.py +879 -0
  143. lorebase_store/storage.py +1478 -0
  144. lorebase_store/telemetry.py +142 -0
  145. lorebase_store/testing.py +108 -0
  146. lorebase_store/tracing.py +505 -0
  147. lorebase_store/traverse.py +578 -0
  148. lorebase_store/vault/__init__.py +50 -0
  149. lorebase_store/vault/keys.py +216 -0
  150. lorebase_store/vault/quotes.py +133 -0
  151. lorebase_store/vault/rotation.py +209 -0
  152. lorebase_store/vault/settings.py +152 -0
  153. lorebase_store/vault/store.py +987 -0
  154. lorebase_store/vault/transfer.py +558 -0
  155. lorebase_store/webhooks/__init__.py +24 -0
  156. lorebase_store/webhooks/delivery.py +637 -0
  157. lorebase_store/webhooks/keys.py +126 -0
  158. lorebase_store/webhooks/repository.py +142 -0
  159. lorebase_store/webhooks/settings.py +138 -0
  160. lorebase_store/webhooks/signing.py +50 -0
  161. lorebase_store-0.2.3.dist-info/METADATA +13 -0
  162. lorebase_store-0.2.3.dist-info/RECORD +163 -0
  163. lorebase_store-0.2.3.dist-info/WHEEL +4 -0
@@ -0,0 +1,133 @@
1
+ """Run Alembic migrations programmatically and expose the expected head revisions.
2
+
3
+ The Alembic environment lives in `packages/store/migrations` (shipped in the wheel as
4
+ `lorebase_store/_migrations`). Settings not passed explicitly are loaded with `load_settings()`
5
+ by the environment; revisions read `config.attributes["store_settings"]`.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ from collections.abc import Iterable
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ from alembic import command
16
+ from alembic.config import Config
17
+ from alembic.script import ScriptDirectory
18
+ from alembic.util import CommandError
19
+
20
+ from lorebase_store.settings import DatabaseSettings, StoreSettings
21
+
22
+ DATABASE_ATTRIBUTE = "database_settings"
23
+ STORE_ATTRIBUTE = "store_settings"
24
+ URL_ATTRIBUTE = "database_url"
25
+
26
+ DYNAMIC_INDEX_PREFIXES = ("embeddings_hnsw_", "mat_records_attr_", "ix_mat_records_bm25")
27
+ """Indexes created from configuration or schema at runtime, the optional BM25 index
28
+ (`lorebase_store.bm25`) included; schema comparison skips them."""
29
+
30
+ PROFILE_INDEXES = ("ix_mat_records_values", "ix_mat_lexicon_branch_word")
31
+ """Indexes of the models that a storage profile may leave out (`lorebase_store.storage`);
32
+ schema comparison skips them whether they exist or not."""
33
+
34
+ PARTITION_NAME = re.compile(r"^(?P<parent>[a-z_]+)_p(?P<remainder>\d+)$")
35
+ """Hash partitions are named `<table>_p<remainder>`."""
36
+
37
+ _PACKAGED_SCRIPTS = Path(__file__).resolve().parent / "_migrations"
38
+ _SOURCE_SCRIPTS = Path(__file__).resolve().parents[2] / "migrations"
39
+
40
+
41
+ def script_location() -> Path:
42
+ """Directory of the Alembic environment: the packaged copy, else the source tree."""
43
+ return _PACKAGED_SCRIPTS if _PACKAGED_SCRIPTS.is_dir() else _SOURCE_SCRIPTS
44
+
45
+
46
+ def include_object(
47
+ obj: Any, name: str | None, type_: str, reflected: bool, compare_to: Any
48
+ ) -> bool:
49
+ """Schema comparison filter: skip hash partitions, runtime-managed indexes and the
50
+ indexes a storage profile manages."""
51
+ if type_ == "index" and name in PROFILE_INDEXES:
52
+ return False
53
+ if not reflected or compare_to is not None or name is None:
54
+ return True
55
+ if type_ == "table":
56
+ return PARTITION_NAME.match(name) is None
57
+ if type_ == "index":
58
+ return not name.startswith(DYNAMIC_INDEX_PREFIXES)
59
+ return True
60
+
61
+
62
+ def alembic_config(
63
+ database: DatabaseSettings | None = None,
64
+ store: StoreSettings | None = None,
65
+ *,
66
+ url: str | None = None,
67
+ ) -> Config:
68
+ """Alembic configuration; `url` overrides `database.dsn`."""
69
+ config = Config()
70
+ config.set_main_option("script_location", str(script_location()))
71
+ for key, value in (
72
+ (DATABASE_ATTRIBUTE, database),
73
+ (STORE_ATTRIBUTE, store),
74
+ (URL_ATTRIBUTE, url),
75
+ ):
76
+ if value is not None:
77
+ config.attributes[key] = value
78
+ return config
79
+
80
+
81
+ def head_revisions() -> tuple[str, ...]:
82
+ """Alembic head revisions of this code, for readiness checks."""
83
+ return tuple(ScriptDirectory.from_config(alembic_config()).get_heads())
84
+
85
+
86
+ class RevisionMismatchError(CommandError):
87
+ """The database is at a revision this code does not know: a newer version migrated it."""
88
+
89
+
90
+ def unknown_revisions(script: ScriptDirectory, current: Iterable[str]) -> tuple[str, ...]:
91
+ """Revisions of `current` (the database's) that the migration scripts of this code lack."""
92
+ known = {revision.revision for revision in script.walk_revisions()}
93
+ return tuple(sorted({revision for revision in current if revision not in known}))
94
+
95
+
96
+ def check_known_revisions(script: ScriptDirectory, current: Iterable[str]) -> None:
97
+ """Refuse to migrate a database that a newer version already migrated.
98
+
99
+ Alembic alone stops with "Can't locate revision"; this names both sides and the way out.
100
+ """
101
+ unknown = unknown_revisions(script, current)
102
+ if not unknown:
103
+ return
104
+ heads = ", ".join(sorted(script.get_heads())) or "none"
105
+ raise RevisionMismatchError(
106
+ f"the database is at revision {', '.join(unknown)}, which this code does not know "
107
+ f"(its newest revision is {heads}): a newer Lorebase migrated this database. Run the "
108
+ "version that did (with docker compose: `docker compose build` then `up`, or "
109
+ "`make up`, which rebuild the images from the checkout), or restore a backup taken "
110
+ "before that upgrade. Older code cannot downgrade it."
111
+ )
112
+
113
+
114
+ def upgrade(
115
+ revision: str = "head",
116
+ *,
117
+ database: DatabaseSettings | None = None,
118
+ store: StoreSettings | None = None,
119
+ url: str | None = None,
120
+ ) -> None:
121
+ """Upgrade the database to `revision`."""
122
+ command.upgrade(alembic_config(database, store, url=url), revision)
123
+
124
+
125
+ def downgrade(
126
+ revision: str = "base",
127
+ *,
128
+ database: DatabaseSettings | None = None,
129
+ store: StoreSettings | None = None,
130
+ url: str | None = None,
131
+ ) -> None:
132
+ """Downgrade the database to `revision`."""
133
+ command.downgrade(alembic_config(database, store, url=url), revision)
@@ -0,0 +1,136 @@
1
+ """SQLAlchemy models of every Lorebase table (design 7). `metadata` is the migration target."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from lorebase_store.models.base import Base
6
+ from lorebase_store.models.governance import (
7
+ ApiKey,
8
+ ApiKeyUsage,
9
+ AuditEntry,
10
+ AuditReadEntry,
11
+ Grant,
12
+ Group,
13
+ GroupMember,
14
+ OperationDeferredEvent,
15
+ OperationInvocation,
16
+ Principal,
17
+ RateLimitBucket,
18
+ WebSession,
19
+ )
20
+ from lorebase_store.models.ingestion import (
21
+ Document,
22
+ DocumentBlob,
23
+ DocumentChunk,
24
+ ExtractionCacheEntry,
25
+ ExtractionJob,
26
+ InferenceEndpointMode,
27
+ InstallationSecret,
28
+ SchemaSuggestion,
29
+ SourceRun,
30
+ VaultEntry,
31
+ VaultLineage,
32
+ VaultTombstone,
33
+ )
34
+ from lorebase_store.models.materialized import (
35
+ BranchMaterialization,
36
+ Embedding,
37
+ EmbeddingCursor,
38
+ MatHistory,
39
+ MatLexicon,
40
+ MatLineageMap,
41
+ MatLink,
42
+ MatRecord,
43
+ MatSchema,
44
+ StorageTask,
45
+ )
46
+ from lorebase_store.models.proposals import (
47
+ Conflict,
48
+ ConflictResolution,
49
+ MergeAttempt,
50
+ Proposal,
51
+ ProposalItem,
52
+ ProposalReview,
53
+ )
54
+ from lorebase_store.models.queues import Job, OutboxConsumer, OutboxEvent, OutboxPending
55
+ from lorebase_store.models.tracing import (
56
+ AgentTraceSession,
57
+ AgentTraceSessionDomain,
58
+ AgentTraceStep,
59
+ )
60
+ from lorebase_store.models.versioning import (
61
+ ChangesetEntry,
62
+ Domain,
63
+ Provenance,
64
+ Ref,
65
+ RefLogEntry,
66
+ Revision,
67
+ RevisionParent,
68
+ StoredObject,
69
+ TreeNode,
70
+ )
71
+ from lorebase_store.models.webhooks import Webhook, WebhookDelivery
72
+
73
+ metadata = Base.metadata
74
+
75
+ __all__ = [
76
+ "AgentTraceSession",
77
+ "AgentTraceSessionDomain",
78
+ "AgentTraceStep",
79
+ "ApiKey",
80
+ "ApiKeyUsage",
81
+ "AuditEntry",
82
+ "AuditReadEntry",
83
+ "Base",
84
+ "BranchMaterialization",
85
+ "ChangesetEntry",
86
+ "Conflict",
87
+ "ConflictResolution",
88
+ "Document",
89
+ "DocumentBlob",
90
+ "DocumentChunk",
91
+ "Domain",
92
+ "Embedding",
93
+ "EmbeddingCursor",
94
+ "ExtractionCacheEntry",
95
+ "ExtractionJob",
96
+ "Grant",
97
+ "Group",
98
+ "GroupMember",
99
+ "InferenceEndpointMode",
100
+ "InstallationSecret",
101
+ "Job",
102
+ "MatHistory",
103
+ "MatLexicon",
104
+ "MatLineageMap",
105
+ "MatLink",
106
+ "MatRecord",
107
+ "MatSchema",
108
+ "MergeAttempt",
109
+ "OperationDeferredEvent",
110
+ "OperationInvocation",
111
+ "OutboxConsumer",
112
+ "OutboxEvent",
113
+ "OutboxPending",
114
+ "Principal",
115
+ "Proposal",
116
+ "ProposalItem",
117
+ "ProposalReview",
118
+ "Provenance",
119
+ "RateLimitBucket",
120
+ "Ref",
121
+ "RefLogEntry",
122
+ "Revision",
123
+ "RevisionParent",
124
+ "SchemaSuggestion",
125
+ "SourceRun",
126
+ "StorageTask",
127
+ "StoredObject",
128
+ "TreeNode",
129
+ "VaultEntry",
130
+ "VaultLineage",
131
+ "VaultTombstone",
132
+ "WebSession",
133
+ "Webhook",
134
+ "WebhookDelivery",
135
+ "metadata",
136
+ ]
@@ -0,0 +1,64 @@
1
+ """Declarative base, constraint naming convention and shared column helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from enum import StrEnum
7
+ from typing import Annotated, Any
8
+
9
+ from sqlalchemy import (
10
+ CheckConstraint,
11
+ DateTime,
12
+ Enum,
13
+ ForeignKeyConstraint,
14
+ LargeBinary,
15
+ MetaData,
16
+ Text,
17
+ )
18
+ from sqlalchemy.dialects.postgresql import JSONB
19
+ from sqlalchemy.orm import DeclarativeBase, mapped_column
20
+
21
+ NAMING_CONVENTION = {
22
+ "ix": "ix_%(table_name)s_%(column_0_N_name)s",
23
+ "uq": "uq_%(table_name)s_%(column_0_N_name)s",
24
+ "ck": "ck_%(table_name)s_%(constraint_name)s",
25
+ "fk": "fk_%(table_name)s_%(column_0_N_name)s_%(referred_table_name)s",
26
+ "pk": "pk_%(table_name)s",
27
+ }
28
+
29
+ HASH_PARTITIONED = {"postgresql_partition_by": "HASH (domain_id)"}
30
+ """Table option for tables hash-partitioned on `domain_id` (partitions come from migrations)."""
31
+
32
+
33
+ class Base(DeclarativeBase):
34
+ """Base of every Lorebase table."""
35
+
36
+ metadata = MetaData(naming_convention=NAMING_CONVENTION)
37
+ type_annotation_map = { # noqa: RUF012
38
+ dict[str, Any]: JSONB,
39
+ bytes: LargeBinary,
40
+ str: Text,
41
+ datetime: DateTime(timezone=True),
42
+ }
43
+
44
+
45
+ H32 = bytes
46
+ """A 32-byte SHA-256 digest stored as `bytea`."""
47
+
48
+ DomainKey = Annotated[str, mapped_column(Text, primary_key=True)]
49
+ """`domain_id` as the leading primary key column."""
50
+
51
+
52
+ def h32_check(column: str) -> CheckConstraint:
53
+ """Check that `column` holds exactly 32 bytes."""
54
+ return CheckConstraint(f"octet_length({column}) = 32", name=f"{column}_h32")
55
+
56
+
57
+ def domain_fk(*, ondelete: str = "CASCADE") -> ForeignKeyConstraint:
58
+ """`domain_id` references `domains.id`; rows go with their Domain."""
59
+ return ForeignKeyConstraint(["domain_id"], ["domains.id"], ondelete=ondelete)
60
+
61
+
62
+ def pg_enum(enum: type[StrEnum], name: str) -> Enum:
63
+ """Native Postgres enum type `name` storing the member values of `enum`."""
64
+ return Enum(enum, name=name, values_callable=lambda members: [m.value for m in members])
@@ -0,0 +1,132 @@
1
+ """Closed value sets stored as native Postgres enum types."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from enum import StrEnum
6
+
7
+ from lorebase_store.models.base import pg_enum
8
+
9
+
10
+ class RefKind(StrEnum):
11
+ """`branch` moves; `tag` is an immutable pointer (design 6.5); `snapshot` holds the
12
+ materialized rows of a past Revision for reads at it (`materialize.snapshot`)."""
13
+
14
+ BRANCH = "branch"
15
+ TAG = "tag"
16
+ SNAPSHOT = "snapshot"
17
+
18
+
19
+ class Materialization(StrEnum):
20
+ """Branch materialization mode (design 6.11)."""
21
+
22
+ FULL = "full"
23
+ OVERLAY = "overlay"
24
+ NONE = "none"
25
+ BUILDING = "building"
26
+ """A full branch whose rows a background job is still writing from its tree; reads of
27
+ its head and commits wait for it (`materialize.background`)."""
28
+
29
+
30
+ class ProposalOrigin(StrEnum):
31
+ """What opened a Proposal."""
32
+
33
+ MANUAL = "manual"
34
+ SOURCE_SYNC = "source_sync"
35
+ EXTRACTION = "extraction"
36
+ OPERATION = "operation"
37
+
38
+
39
+ class ProposalStatus(StrEnum):
40
+ """Proposal lifecycle."""
41
+
42
+ OPEN = "open"
43
+ MERGED = "merged"
44
+ CLOSED = "closed"
45
+
46
+
47
+ class ReviewVerdict(StrEnum):
48
+ """Outcome of one Proposal review."""
49
+
50
+ APPROVE = "approve"
51
+ REQUEST_CHANGES = "request_changes"
52
+ COMMENT = "comment"
53
+
54
+
55
+ class ItemDecision(StrEnum):
56
+ """Decision on one extraction Proposal item."""
57
+
58
+ PENDING = "pending"
59
+ ACCEPTED = "accepted"
60
+ REJECTED = "rejected"
61
+
62
+
63
+ class MergeAttemptStatus(StrEnum):
64
+ """Merge attempt lifecycle (design 6.8 step 5, 6.10)."""
65
+
66
+ CONFLICTED = "conflicted"
67
+ STALE = "stale"
68
+ RESOLVED = "resolved"
69
+ MERGED = "merged"
70
+ ABANDONED = "abandoned"
71
+
72
+
73
+ class PrincipalType(StrEnum):
74
+ """Kind of authenticated actor (design 13.2)."""
75
+
76
+ USER = "user"
77
+ SERVICE = "service"
78
+ API_KEY = "api_key"
79
+
80
+
81
+ class GrantScope(StrEnum):
82
+ """What a grant applies to (design 10.2)."""
83
+
84
+ DOMAIN = "domain"
85
+ KIND = "kind"
86
+ OPERATION = "operation"
87
+ BRANCH = "branch"
88
+
89
+
90
+ class InvocationStatus(StrEnum):
91
+ """Operation invocation status (design 10.1)."""
92
+
93
+ PENDING = "pending"
94
+ COMMITTED = "committed"
95
+ PROPOSED = "proposed"
96
+ REJECTED = "rejected"
97
+ DRY_RUN = "dry_run"
98
+ FAILED = "failed"
99
+
100
+
101
+ class JobStatus(StrEnum):
102
+ """Background job lifecycle; `queued` jobs are claimed with SKIP LOCKED."""
103
+
104
+ QUEUED = "queued"
105
+ RUNNING = "running"
106
+ SUCCEEDED = "succeeded"
107
+ FAILED = "failed"
108
+ CANCELLED = "cancelled"
109
+
110
+
111
+ class RunStatus(StrEnum):
112
+ """Lifecycle of Source runs and extraction jobs."""
113
+
114
+ QUEUED = "queued"
115
+ RUNNING = "running"
116
+ SUCCEEDED = "succeeded"
117
+ FAILED = "failed"
118
+ CANCELLED = "cancelled"
119
+
120
+
121
+ REF_KIND = pg_enum(RefKind, "ref_kind")
122
+ MATERIALIZATION = pg_enum(Materialization, "materialization")
123
+ PROPOSAL_ORIGIN = pg_enum(ProposalOrigin, "proposal_origin")
124
+ PROPOSAL_STATUS = pg_enum(ProposalStatus, "proposal_status")
125
+ REVIEW_VERDICT = pg_enum(ReviewVerdict, "review_verdict")
126
+ ITEM_DECISION = pg_enum(ItemDecision, "item_decision")
127
+ MERGE_ATTEMPT_STATUS = pg_enum(MergeAttemptStatus, "merge_attempt_status")
128
+ PRINCIPAL_TYPE = pg_enum(PrincipalType, "principal_type")
129
+ GRANT_SCOPE = pg_enum(GrantScope, "grant_scope")
130
+ INVOCATION_STATUS = pg_enum(InvocationStatus, "invocation_status")
131
+ JOB_STATUS = pg_enum(JobStatus, "job_status")
132
+ RUN_STATUS = pg_enum(RunStatus, "run_status")