textus 0.20.2 → 0.26.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.
Files changed (175) hide show
  1. checksums.yaml +4 -4
  2. data/ARCHITECTURE.md +148 -45
  3. data/CHANGELOG.md +194 -0
  4. data/README.md +8 -5
  5. data/SPEC.md +54 -15
  6. data/docs/conventions.md +10 -0
  7. data/lib/textus/application/caps.rb +49 -0
  8. data/lib/textus/application/context.rb +2 -2
  9. data/lib/textus/application/envelope/reader.rb +44 -0
  10. data/lib/textus/application/{writes/envelope_io.rb → envelope/writer.rb} +24 -50
  11. data/lib/textus/application/maintenance/key_delete_prefix.rb +44 -0
  12. data/lib/textus/application/maintenance/key_mv_prefix.rb +57 -0
  13. data/lib/textus/application/maintenance/migrate.rb +59 -0
  14. data/lib/textus/application/maintenance/rule_lint.rb +65 -0
  15. data/lib/textus/application/maintenance/zone_mv.rb +60 -0
  16. data/lib/textus/application/maintenance.rb +17 -0
  17. data/lib/textus/application/projection.rb +12 -10
  18. data/lib/textus/application/read/audit.rb +106 -0
  19. data/lib/textus/application/read/blame.rb +91 -0
  20. data/lib/textus/application/read/deps.rb +34 -0
  21. data/lib/textus/application/read/freshness.rb +110 -0
  22. data/lib/textus/application/read/get.rb +75 -0
  23. data/lib/textus/application/read/get_or_refresh.rb +63 -0
  24. data/lib/textus/application/read/list.rb +25 -0
  25. data/lib/textus/application/read/policy_explain.rb +47 -0
  26. data/lib/textus/application/read/published.rb +25 -0
  27. data/lib/textus/application/read/pulse.rb +101 -0
  28. data/lib/textus/application/read/rdeps.rb +35 -0
  29. data/lib/textus/application/read/schema_envelope.rb +26 -0
  30. data/lib/textus/application/read/stale.rb +23 -0
  31. data/lib/textus/application/read/uid.rb +30 -0
  32. data/lib/textus/application/read/validate_all.rb +32 -0
  33. data/lib/textus/application/{reads → read}/validator.rb +2 -2
  34. data/lib/textus/application/read/where.rb +26 -0
  35. data/lib/textus/application/use_case.rb +22 -0
  36. data/lib/textus/application/write/accept.rb +102 -0
  37. data/lib/textus/application/{writes → write}/authority_gate.rb +3 -3
  38. data/lib/textus/application/write/delete.rb +45 -0
  39. data/lib/textus/application/{writes → write}/materializer.rb +14 -15
  40. data/lib/textus/application/write/mv.rb +118 -0
  41. data/lib/textus/application/write/publish.rb +96 -0
  42. data/lib/textus/application/write/put.rb +49 -0
  43. data/lib/textus/application/write/refresh_all.rb +63 -0
  44. data/lib/textus/application/{refresh/orchestrator.rb → write/refresh_orchestrator.rb} +32 -8
  45. data/lib/textus/application/write/refresh_worker.rb +134 -0
  46. data/lib/textus/application/write/reject.rb +62 -0
  47. data/lib/textus/{intro.rb → boot.rb} +49 -29
  48. data/lib/textus/builder/pipeline.rb +5 -5
  49. data/lib/textus/cli/group/mcp.rb +9 -0
  50. data/lib/textus/cli/group/zone.rb +9 -0
  51. data/lib/textus/cli/verb/accept.rb +1 -1
  52. data/lib/textus/cli/verb/audit.rb +4 -2
  53. data/lib/textus/cli/verb/blame.rb +1 -1
  54. data/lib/textus/cli/verb/boot.rb +13 -0
  55. data/lib/textus/cli/verb/build.rb +2 -2
  56. data/lib/textus/cli/verb/delete.rb +1 -1
  57. data/lib/textus/cli/verb/deps.rb +1 -1
  58. data/lib/textus/cli/verb/doctor.rb +1 -1
  59. data/lib/textus/cli/verb/freshness.rb +1 -1
  60. data/lib/textus/cli/verb/get.rb +1 -1
  61. data/lib/textus/cli/verb/hook_run.rb +3 -4
  62. data/lib/textus/cli/verb/hooks.rb +11 -14
  63. data/lib/textus/cli/verb/key_delete.rb +24 -0
  64. data/lib/textus/cli/verb/list.rb +1 -1
  65. data/lib/textus/cli/verb/mcp_serve.rb +17 -0
  66. data/lib/textus/cli/verb/migrate.rb +18 -0
  67. data/lib/textus/cli/verb/mv.rb +11 -3
  68. data/lib/textus/cli/verb/published.rb +1 -1
  69. data/lib/textus/cli/verb/pulse.rb +17 -0
  70. data/lib/textus/cli/verb/put.rb +8 -6
  71. data/lib/textus/cli/verb/rdeps.rb +1 -1
  72. data/lib/textus/cli/verb/refresh.rb +1 -1
  73. data/lib/textus/cli/verb/refresh_stale.rb +1 -1
  74. data/lib/textus/cli/verb/reject.rb +1 -1
  75. data/lib/textus/cli/verb/rule_explain.rb +1 -1
  76. data/lib/textus/cli/verb/rule_lint.rb +18 -0
  77. data/lib/textus/cli/verb/schema.rb +1 -1
  78. data/lib/textus/cli/verb/uid.rb +1 -1
  79. data/lib/textus/cli/verb/where.rb +1 -1
  80. data/lib/textus/cli/verb/zone_mv.rb +19 -0
  81. data/lib/textus/cli/verb.rb +4 -4
  82. data/lib/textus/cli.rb +1 -1
  83. data/lib/textus/doctor/check/audit_log.rb +2 -2
  84. data/lib/textus/doctor/check/handler_allowlist.rb +2 -2
  85. data/lib/textus/doctor/check/hooks.rb +4 -3
  86. data/lib/textus/doctor/check/illegal_keys.rb +2 -2
  87. data/lib/textus/doctor/check/intake_registration.rb +2 -2
  88. data/lib/textus/doctor/check/manifest_files.rb +2 -2
  89. data/lib/textus/doctor/check/protocol_version.rb +2 -2
  90. data/lib/textus/doctor/check/refresh_locks.rb +2 -2
  91. data/lib/textus/doctor/check/rule_ambiguity.rb +2 -2
  92. data/lib/textus/doctor/check/schema_parse_error.rb +1 -1
  93. data/lib/textus/doctor/check/schema_violations.rb +1 -1
  94. data/lib/textus/doctor/check/schemas.rb +2 -2
  95. data/lib/textus/doctor/check/sentinels.rb +2 -2
  96. data/lib/textus/doctor/check/templates.rb +2 -2
  97. data/lib/textus/doctor/check/unowned_schema_fields.rb +1 -1
  98. data/lib/textus/doctor/check.rb +5 -3
  99. data/lib/textus/doctor.rb +24 -27
  100. data/lib/textus/domain/authorizer.rb +4 -4
  101. data/lib/textus/{application → domain}/policy/predicates/accept_authority_signed.rb +2 -2
  102. data/lib/textus/{application → domain}/policy/predicates/schema_valid.rb +1 -1
  103. data/lib/textus/{application → domain}/policy/promotion.rb +1 -1
  104. data/lib/textus/domain/staleness/generator_check.rb +2 -2
  105. data/lib/textus/domain/staleness/intake_check.rb +2 -2
  106. data/lib/textus/domain/staleness.rb +1 -1
  107. data/lib/textus/errors.rb +16 -0
  108. data/lib/textus/hooks/builtin.rb +14 -14
  109. data/lib/textus/hooks/context.rb +13 -13
  110. data/lib/textus/hooks/error_log.rb +32 -0
  111. data/lib/textus/hooks/{bus.rb → event_bus.rb} +41 -53
  112. data/lib/textus/hooks/loader.rb +29 -3
  113. data/lib/textus/hooks/rpc_registry.rb +77 -0
  114. data/lib/textus/infra/audit_log.rb +126 -16
  115. data/lib/textus/infra/audit_subscriber.rb +6 -7
  116. data/lib/textus/infra/refresh/detached.rb +1 -1
  117. data/lib/textus/key/path.rb +7 -3
  118. data/lib/textus/manifest/data.rb +78 -0
  119. data/lib/textus/manifest/entry/base.rb +44 -7
  120. data/lib/textus/manifest/entry/derived.rb +41 -6
  121. data/lib/textus/manifest/entry/intake.rb +15 -3
  122. data/lib/textus/manifest/entry/leaf.rb +6 -5
  123. data/lib/textus/manifest/entry/nested.rb +42 -3
  124. data/lib/textus/manifest/entry/parser.rb +8 -44
  125. data/lib/textus/manifest/entry/validators/events.rb +2 -2
  126. data/lib/textus/manifest/entry/validators/format_matrix.rb +5 -4
  127. data/lib/textus/manifest/entry/validators/index_filename.rb +2 -1
  128. data/lib/textus/manifest/entry/validators/inject_boot.rb +19 -0
  129. data/lib/textus/manifest/entry/validators/publish_each.rb +4 -3
  130. data/lib/textus/manifest/entry/validators.rb +1 -1
  131. data/lib/textus/manifest/entry.rb +3 -0
  132. data/lib/textus/manifest/policy.rb +48 -0
  133. data/lib/textus/manifest/resolver.rb +18 -18
  134. data/lib/textus/manifest/rules.rb +1 -1
  135. data/lib/textus/manifest/schema.rb +20 -6
  136. data/lib/textus/manifest.rb +53 -101
  137. data/lib/textus/mcp/errors.rb +32 -0
  138. data/lib/textus/mcp/server.rb +127 -0
  139. data/lib/textus/mcp/session.rb +31 -0
  140. data/lib/textus/mcp/tool_schemas.rb +71 -0
  141. data/lib/textus/mcp/tools.rb +129 -0
  142. data/lib/textus/mcp.rb +6 -0
  143. data/lib/textus/schema/tools.rb +14 -10
  144. data/lib/textus/session.rb +84 -0
  145. data/lib/textus/store.rb +17 -8
  146. data/lib/textus/version.rb +1 -1
  147. data/lib/textus.rb +8 -1
  148. metadata +65 -38
  149. data/lib/textus/application/reads/audit.rb +0 -69
  150. data/lib/textus/application/reads/blame.rb +0 -82
  151. data/lib/textus/application/reads/deps.rb +0 -26
  152. data/lib/textus/application/reads/freshness.rb +0 -88
  153. data/lib/textus/application/reads/get.rb +0 -67
  154. data/lib/textus/application/reads/get_or_refresh.rb +0 -51
  155. data/lib/textus/application/reads/list.rb +0 -17
  156. data/lib/textus/application/reads/policy_explain.rb +0 -39
  157. data/lib/textus/application/reads/published.rb +0 -17
  158. data/lib/textus/application/reads/rdeps.rb +0 -27
  159. data/lib/textus/application/reads/schema_envelope.rb +0 -18
  160. data/lib/textus/application/reads/stale.rb +0 -15
  161. data/lib/textus/application/reads/uid.rb +0 -23
  162. data/lib/textus/application/reads/validate_all.rb +0 -24
  163. data/lib/textus/application/reads/where.rb +0 -18
  164. data/lib/textus/application/refresh/all.rb +0 -52
  165. data/lib/textus/application/refresh/worker.rb +0 -116
  166. data/lib/textus/application/writes/accept.rb +0 -89
  167. data/lib/textus/application/writes/delete.rb +0 -33
  168. data/lib/textus/application/writes/mv.rb +0 -105
  169. data/lib/textus/application/writes/publish.rb +0 -162
  170. data/lib/textus/application/writes/put.rb +0 -37
  171. data/lib/textus/application/writes/reject.rb +0 -50
  172. data/lib/textus/cli/verb/intro.rb +0 -13
  173. data/lib/textus/infra/event_bus.rb +0 -27
  174. data/lib/textus/manifest/entry/validators/inject_intro.rb +0 -21
  175. data/lib/textus/operations.rb +0 -169
@@ -1,169 +0,0 @@
1
- module Textus
2
- # Single canonical entrypoint for invoking application use-cases against a
3
- # store. Public surface is flat — one method per use case:
4
- #
5
- # ops = Textus::Operations.for(store, role: "agent")
6
- # ops.put(key, body: "...")
7
- # ops.get(key) # pure read
8
- # ops.get_or_refresh(key) # read + refresh-on-stale
9
- # ops.refresh(key) # synchronous worker refresh
10
- # ops.refresh_all(prefix: ..., zone: ...)
11
- class Operations
12
- def self.for(store, role: Role::DEFAULT, correlation_id: nil, dry_run: false)
13
- new(
14
- ctx: Application::Context.build(role: role, correlation_id: correlation_id, dry_run: dry_run),
15
- manifest: store.manifest,
16
- file_store: store.file_store,
17
- schemas: store.schemas,
18
- audit_log: store.audit_log,
19
- bus: store.bus,
20
- root: store.root,
21
- store: store,
22
- )
23
- end
24
-
25
- attr_reader :ctx, :store
26
-
27
- # rubocop:disable Metrics/ParameterLists
28
- def initialize(ctx:, manifest:, file_store:, schemas:, audit_log:, bus:, root:, store:)
29
- @ctx = ctx
30
- @manifest = manifest
31
- @file_store = file_store
32
- @schemas = schemas
33
- @audit_log = audit_log
34
- @bus = bus
35
- @root = root
36
- @store = store
37
- @authorizer = Textus::Domain::Authorizer.new(manifest: @manifest)
38
- end
39
- # rubocop:enable Metrics/ParameterLists
40
-
41
- def with_role(role)
42
- self.class.new(
43
- ctx: @ctx.with_role(role),
44
- manifest: @manifest, file_store: @file_store, schemas: @schemas,
45
- audit_log: @audit_log, bus: @bus,
46
- root: @root, store: @store
47
- )
48
- end
49
-
50
- def hook_context
51
- @hook_context ||= Textus::Hooks::Context.new(ops: self)
52
- end
53
-
54
- # writes
55
- def put(...)
56
- Application::Writes::Put.new(
57
- ctx: @ctx, manifest: @manifest, envelope_io: envelope_io,
58
- bus: @bus, authorizer: @authorizer, hook_context: hook_context
59
- ).call(...)
60
- end
61
-
62
- def delete(...)
63
- Application::Writes::Delete.new(
64
- ctx: @ctx, manifest: @manifest, envelope_io: envelope_io,
65
- bus: @bus, authorizer: @authorizer, hook_context: hook_context
66
- ).call(...)
67
- end
68
-
69
- def mv(...)
70
- Application::Writes::Mv.new(
71
- ctx: @ctx, manifest: @manifest, envelope_io: envelope_io,
72
- bus: @bus, authorizer: @authorizer, hook_context: hook_context
73
- ).call(...)
74
- end
75
-
76
- def accept(...)
77
- Application::Writes::Accept.new(
78
- ctx: @ctx, manifest: @manifest, file_store: @file_store, schemas: @schemas,
79
- envelope_io: envelope_io, bus: @bus, authorizer: @authorizer, hook_context: hook_context
80
- ).call(...)
81
- end
82
-
83
- def reject(...)
84
- Application::Writes::Reject.new(
85
- ctx: @ctx, manifest: @manifest, file_store: @file_store,
86
- envelope_io: envelope_io, bus: @bus, authorizer: @authorizer, hook_context: hook_context
87
- ).call(...)
88
- end
89
-
90
- def publish(...)
91
- Application::Writes::Publish.new(
92
- ctx: @ctx, manifest: @manifest, file_store: @file_store,
93
- bus: @bus, root: @root, store: @store, hook_context: hook_context
94
- ).call(...)
95
- end
96
-
97
- # reads
98
- def get(...)
99
- Application::Reads::Get.new(ctx: @ctx, manifest: @manifest, file_store: @file_store).call(...)
100
- end
101
-
102
- def get_or_refresh(...)
103
- Application::Reads::GetOrRefresh.new(
104
- manifest: @manifest,
105
- get: Application::Reads::Get.new(ctx: @ctx, manifest: @manifest, file_store: @file_store),
106
- orchestrator: orchestrator,
107
- ).call(...)
108
- end
109
-
110
- def list(...) = Application::Reads::List.new(manifest: @manifest).call(...)
111
- def where(...) = Application::Reads::Where.new(manifest: @manifest).call(...)
112
- def uid(...) = Application::Reads::Uid.new(ctx: @ctx, manifest: @manifest, file_store: @file_store).call(...)
113
- def schema_envelope(...) = Application::Reads::SchemaEnvelope.new(manifest: @manifest, schemas: @schemas).call(...)
114
- def deps(...) = Application::Reads::Deps.new(manifest: @manifest).call(...)
115
- def rdeps(...) = Application::Reads::Rdeps.new(manifest: @manifest).call(...)
116
- def published(...) = Application::Reads::Published.new(manifest: @manifest).call(...)
117
- def stale(...) = Application::Reads::Stale.new(manifest: @manifest).call(...)
118
- def audit(...) = Application::Reads::Audit.new(manifest: @manifest, root: @root).call(...)
119
- def blame(...) = Application::Reads::Blame.new(manifest: @manifest, root: @root).call(...)
120
- def policy_explain(...) = Application::Reads::PolicyExplain.new(manifest: @manifest).call(...)
121
- def freshness(...) = Application::Reads::Freshness.new(ctx: @ctx, manifest: @manifest, file_store: @file_store).call(...)
122
-
123
- def validate_all(...)
124
- Application::Reads::ValidateAll.new(
125
- ctx: @ctx, manifest: @manifest, file_store: @file_store, schemas: @schemas, audit_log: @audit_log,
126
- ).call(...)
127
- end
128
-
129
- # refresh
130
- def refresh(key) = refresh_worker.run(key)
131
-
132
- def refresh_all(**)
133
- Application::Refresh::All.new(
134
- ctx: @ctx, manifest: @manifest, envelope_io: envelope_io, bus: @bus,
135
- store: @store, authorizer: @authorizer, hook_context: hook_context
136
- ).call(**)
137
- end
138
-
139
- private
140
-
141
- def envelope_io
142
- @envelope_io ||= Application::Writes::EnvelopeIO.new(
143
- file_store: @file_store,
144
- manifest: @manifest,
145
- schemas: @schemas,
146
- audit_log: @audit_log,
147
- ctx: @ctx,
148
- )
149
- end
150
-
151
- def refresh_worker
152
- @refresh_worker ||= Application::Refresh::Worker.new(
153
- ctx: @ctx, manifest: @manifest, envelope_io: envelope_io, bus: @bus,
154
- store: @store, authorizer: @authorizer, hook_context: hook_context
155
- )
156
- end
157
-
158
- def orchestrator
159
- @orchestrator ||= Application::Refresh::Orchestrator.new(
160
- worker: refresh_worker,
161
- store_root: @root,
162
- bus: @bus,
163
- store: @store,
164
- ctx: @ctx,
165
- hook_context: hook_context,
166
- )
167
- end
168
- end
169
- end