textus 0.43.2 → 0.45.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -0
- data/README.md +3 -3
- data/SPEC.md +15 -13
- data/docs/architecture/README.md +28 -9
- data/docs/reference/conventions.md +8 -9
- data/lib/textus/boot.rb +3 -4
- data/lib/textus/cli/group/fetch.rb +2 -2
- data/lib/textus/cli/group.rb +1 -0
- data/lib/textus/cli/runner.rb +187 -0
- data/lib/textus/cli/verb/build.rb +4 -4
- data/lib/textus/cli/verb/{fetch_stale.rb → fetch_all.rb} +2 -2
- data/lib/textus/cli/verb/get.rb +6 -5
- data/lib/textus/cli/verb/put.rb +3 -3
- data/lib/textus/cli/verb.rb +3 -0
- data/lib/textus/cli.rb +8 -2
- data/lib/textus/contract/around.rb +29 -0
- data/lib/textus/contract/binder.rb +88 -0
- data/lib/textus/contract/resources/cursor.rb +26 -0
- data/lib/textus/contract/sources.rb +39 -0
- data/lib/textus/contract/view.rb +15 -0
- data/lib/textus/contract.rb +68 -8
- data/lib/textus/dispatcher.rb +5 -6
- data/lib/textus/hooks/context.rb +24 -2
- data/lib/textus/maintenance/key_delete_prefix.rb +6 -4
- data/lib/textus/maintenance/key_mv_prefix.rb +7 -5
- data/lib/textus/maintenance/migrate.rb +12 -9
- data/lib/textus/maintenance/rule_lint.rb +4 -3
- data/lib/textus/maintenance/zone_mv.rb +7 -5
- data/lib/textus/manifest/entry/base.rb +1 -1
- data/lib/textus/mcp/catalog.rb +6 -33
- data/lib/textus/projection.rb +2 -2
- data/lib/textus/read/audit.rb +19 -0
- data/lib/textus/read/blame.rb +11 -1
- data/lib/textus/read/deps.rb +15 -1
- data/lib/textus/read/doctor.rb +8 -0
- data/lib/textus/read/freshness.rb +10 -0
- data/lib/textus/read/get.rb +86 -21
- data/lib/textus/read/list.rb +1 -0
- data/lib/textus/read/published.rb +7 -0
- data/lib/textus/read/pulse.rb +1 -0
- data/lib/textus/read/rdeps.rb +14 -0
- data/lib/textus/read/rule_explain.rb +84 -0
- data/lib/textus/read/rule_list.rb +39 -0
- data/lib/textus/read/schema_envelope.rb +3 -2
- data/lib/textus/read/uid.rb +9 -0
- data/lib/textus/read/where.rb +8 -0
- data/lib/textus/role_scope.rb +34 -6
- data/lib/textus/schema/tools.rb +12 -3
- data/lib/textus/version.rb +1 -1
- data/lib/textus/write/accept.rb +8 -0
- data/lib/textus/write/{publish.rb → build.rb} +16 -7
- data/lib/textus/write/delete.rb +13 -0
- data/lib/textus/write/fetch_all.rb +1 -0
- data/lib/textus/write/fetch_orchestrator.rb +1 -1
- data/lib/textus/write/fetch_worker.rb +1 -1
- data/lib/textus/write/mv.rb +16 -0
- data/lib/textus/write/propose.rb +7 -2
- data/lib/textus/write/put.rb +2 -2
- data/lib/textus/write/reject.rb +8 -0
- data/lib/textus/write/retention_sweep.rb +9 -0
- metadata +11 -29
- data/lib/textus/cli/verb/accept.rb +0 -16
- data/lib/textus/cli/verb/audit.rb +0 -34
- data/lib/textus/cli/verb/blame.rb +0 -17
- data/lib/textus/cli/verb/delete.rb +0 -17
- data/lib/textus/cli/verb/deps.rb +0 -14
- data/lib/textus/cli/verb/freshness.rb +0 -17
- data/lib/textus/cli/verb/key_delete.rb +0 -24
- data/lib/textus/cli/verb/list.rb +0 -16
- data/lib/textus/cli/verb/migrate.rb +0 -18
- data/lib/textus/cli/verb/mv.rb +0 -27
- data/lib/textus/cli/verb/propose.rb +0 -28
- data/lib/textus/cli/verb/published.rb +0 -13
- data/lib/textus/cli/verb/pulse.rb +0 -26
- data/lib/textus/cli/verb/rdeps.rb +0 -14
- data/lib/textus/cli/verb/reject.rb +0 -16
- data/lib/textus/cli/verb/retain.rb +0 -19
- data/lib/textus/cli/verb/rule_explain.rb +0 -16
- data/lib/textus/cli/verb/rule_lint.rb +0 -18
- data/lib/textus/cli/verb/rule_list.rb +0 -29
- data/lib/textus/cli/verb/schema.rb +0 -15
- data/lib/textus/cli/verb/uid.rb +0 -15
- data/lib/textus/cli/verb/where.rb +0 -14
- data/lib/textus/cli/verb/zone_mv.rb +0 -19
- data/lib/textus/read/get_or_fetch.rb +0 -69
- data/lib/textus/read/policy_explain.rb +0 -46
- data/lib/textus/read/rules.rb +0 -25
data/lib/textus/write/delete.rb
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
module Textus
|
|
2
2
|
module Write
|
|
3
3
|
class Delete
|
|
4
|
+
extend Textus::Contract::DSL
|
|
5
|
+
|
|
6
|
+
verb :delete
|
|
7
|
+
summary "Delete one entry by key. Single-key, lower blast radius than " \
|
|
8
|
+
"key_delete_prefix; guarded by an optional optimistic-concurrency etag. Returns {ok, key, deleted}."
|
|
9
|
+
surfaces :cli, :ruby, :mcp
|
|
10
|
+
cli "key delete"
|
|
11
|
+
arg :key, String, required: true, positional: true,
|
|
12
|
+
description: "dotted entry key to delete"
|
|
13
|
+
arg :if_etag, String,
|
|
14
|
+
description: "optimistic-concurrency guard: the etag you last read; the delete is rejected if the entry changed since"
|
|
15
|
+
# `call` already returns a wire hash {protocol, ok, key, deleted}; identity response.
|
|
16
|
+
|
|
4
17
|
def initialize(container:, call:)
|
|
5
18
|
@container = container
|
|
6
19
|
@call = call
|
|
@@ -6,6 +6,7 @@ module Textus
|
|
|
6
6
|
verb :fetch_all
|
|
7
7
|
summary "Fetch all stale quarantine entries, optionally scoped by zone/prefix."
|
|
8
8
|
surfaces :cli, :ruby, :mcp
|
|
9
|
+
cli "fetch all"
|
|
9
10
|
arg :prefix, String, description: "only refresh stale entries whose key starts with this dotted prefix"
|
|
10
11
|
arg :zone, String, description: "only refresh stale entries in this quarantine zone (see `pulse` stale list)"
|
|
11
12
|
|
|
@@ -2,7 +2,7 @@ module Textus
|
|
|
2
2
|
module Write
|
|
3
3
|
class FetchOrchestrator
|
|
4
4
|
# Collaborator (not a Dispatcher verb): constructed directly by FetchWorker /
|
|
5
|
-
#
|
|
5
|
+
# Read::Get, which pass their derived hook_context in. That's why this takes
|
|
6
6
|
# hook_context: explicitly while verb use cases derive their own.
|
|
7
7
|
def initialize(worker:, store_root:, events:, hook_context: nil, detached_spawner: nil)
|
|
8
8
|
@worker = worker
|
|
@@ -10,7 +10,7 @@ module Textus
|
|
|
10
10
|
surfaces :cli, :ruby, :mcp
|
|
11
11
|
arg :key, String, required: true, positional: true,
|
|
12
12
|
description: "quarantine-zone entry key to refresh using its declared intake action"
|
|
13
|
-
|
|
13
|
+
view { |outcome| { "outcome" => outcome.class.name.split("::").last.downcase } }
|
|
14
14
|
|
|
15
15
|
FETCH_TIMEOUT_SECONDS = IntakeFetch::FETCH_TIMEOUT_SECONDS
|
|
16
16
|
|
data/lib/textus/write/mv.rb
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
module Textus
|
|
2
2
|
module Write
|
|
3
3
|
class Mv
|
|
4
|
+
extend Textus::Contract::DSL
|
|
5
|
+
|
|
6
|
+
verb :mv
|
|
7
|
+
summary "Rename one entry (same zone + format). Refuses if the target exists. Single-key, lower blast radius than key_mv_prefix."
|
|
8
|
+
surfaces :cli, :ruby, :mcp
|
|
9
|
+
cli "key mv"
|
|
10
|
+
arg :old_key, String, required: true, positional: true,
|
|
11
|
+
description: "current dotted key"
|
|
12
|
+
arg :new_key, String, required: true, positional: true,
|
|
13
|
+
description: "new dotted key (must be the same zone and format as old_key)"
|
|
14
|
+
arg :dry_run, :boolean,
|
|
15
|
+
description: "when true, returns the planned move (from/to paths, uid) without applying it; " \
|
|
16
|
+
"defaults to false, so omitting it applies the move immediately " \
|
|
17
|
+
"(unlike the bulk key_mv_prefix, which defaults to a dry-run plan)"
|
|
18
|
+
# `call` already returns a wire hash; identity response.
|
|
19
|
+
|
|
4
20
|
def initialize(container:, call:)
|
|
5
21
|
@container = container
|
|
6
22
|
@call = call
|
data/lib/textus/write/propose.rb
CHANGED
|
@@ -10,15 +10,20 @@ module Textus
|
|
|
10
10
|
verb :propose
|
|
11
11
|
summary "Write a proposal to the role's propose_zone. Auto-prefixes the key."
|
|
12
12
|
surfaces :cli, :ruby, :mcp
|
|
13
|
+
cli_stdin :json
|
|
13
14
|
arg :key, String, required: true, positional: true,
|
|
14
15
|
description: "key relative to propose_zone, e.g. 'decisions.feature-x'"
|
|
15
|
-
arg :meta, Hash, required:
|
|
16
|
+
arg :meta, Hash, required: false, wire_name: :_meta,
|
|
16
17
|
description: "frontmatter; reads back as `_meta` from `get`. Include a 'proposal:' block naming the target_key"
|
|
17
18
|
arg :body, String,
|
|
18
19
|
description: "markdown/text payload for markdown-format entries; omit (use `content`) for json/yaml entries. Do not send both"
|
|
19
20
|
arg :content, Hash,
|
|
20
21
|
description: "structured payload for json/yaml-format entries; omit (use `body`) for markdown entries. Do not send both"
|
|
21
|
-
|
|
22
|
+
# ADR 0069: every surface receives the raw Envelope and self-shapes — no
|
|
23
|
+
# surface pre-wires the result. Emitting the full wire envelope on every
|
|
24
|
+
# surface is a superset of the old `{uid, etag, key}` (the accepted
|
|
25
|
+
# breaking change; MCP/Ruby now get the full envelope too).
|
|
26
|
+
view { |env, _i| env.to_h_for_wire }
|
|
22
27
|
|
|
23
28
|
def initialize(container:, call:)
|
|
24
29
|
@container = container
|
data/lib/textus/write/put.rb
CHANGED
|
@@ -8,7 +8,7 @@ module Textus
|
|
|
8
8
|
surfaces :cli, :ruby, :mcp
|
|
9
9
|
arg :key, String, required: true, positional: true,
|
|
10
10
|
description: "dotted entry key, e.g. 'knowledge.project'; must resolve to a zone the role may write"
|
|
11
|
-
arg :meta, Hash, required:
|
|
11
|
+
arg :meta, Hash, required: false, wire_name: :_meta,
|
|
12
12
|
description: "frontmatter; reads back as `_meta` from `get`. Schema-validated — call `schema KEY` first"
|
|
13
13
|
arg :body, String,
|
|
14
14
|
description: "markdown/text payload for markdown-format entries; omit (use `content`) for json/yaml entries. Do not send both"
|
|
@@ -16,7 +16,7 @@ module Textus
|
|
|
16
16
|
description: "structured payload for json/yaml-format entries; omit (use `body`) for markdown entries. Do not send both"
|
|
17
17
|
arg :if_etag, String,
|
|
18
18
|
description: "optimistic-concurrency guard: the etag you last read; the write is rejected if the entry changed since"
|
|
19
|
-
|
|
19
|
+
view { |env| { "uid" => env.uid, "etag" => env.etag } }
|
|
20
20
|
|
|
21
21
|
def initialize(container:, call:)
|
|
22
22
|
@container = container
|
data/lib/textus/write/reject.rb
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
module Textus
|
|
2
2
|
module Write
|
|
3
3
|
class Reject
|
|
4
|
+
extend Textus::Contract::DSL
|
|
5
|
+
|
|
6
|
+
verb :reject
|
|
7
|
+
summary "discard a queued proposal without applying it"
|
|
8
|
+
surfaces :cli, :ruby
|
|
9
|
+
cli "reject"
|
|
10
|
+
arg :pending_key, String, required: true, positional: true, description: "the queued proposal's key"
|
|
11
|
+
|
|
4
12
|
def initialize(container:, call:)
|
|
5
13
|
@container = container
|
|
6
14
|
@call = call
|
|
@@ -7,6 +7,15 @@ module Textus
|
|
|
7
7
|
# <root>/archive/<relative-path> first, then deletes. Rows whose zone the
|
|
8
8
|
# caller's role cannot write surface in `failed` rather than aborting.
|
|
9
9
|
class RetentionSweep
|
|
10
|
+
extend Textus::Contract::DSL
|
|
11
|
+
|
|
12
|
+
verb :retain
|
|
13
|
+
summary "Apply each entry's retention policy; prune expired versions."
|
|
14
|
+
surfaces :cli, :ruby
|
|
15
|
+
cli "retain"
|
|
16
|
+
arg :prefix, String, description: "restrict to keys starting with this dotted prefix"
|
|
17
|
+
arg :zone, String, description: "restrict to entries in this zone"
|
|
18
|
+
|
|
10
19
|
def initialize(container:, call:)
|
|
11
20
|
@container = container
|
|
12
21
|
@call = call
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: textus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.45.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrick
|
|
@@ -127,46 +127,29 @@ files:
|
|
|
127
127
|
- lib/textus/cli/group/rule.rb
|
|
128
128
|
- lib/textus/cli/group/schema.rb
|
|
129
129
|
- lib/textus/cli/group/zone.rb
|
|
130
|
+
- lib/textus/cli/runner.rb
|
|
130
131
|
- lib/textus/cli/verb.rb
|
|
131
|
-
- lib/textus/cli/verb/accept.rb
|
|
132
|
-
- lib/textus/cli/verb/audit.rb
|
|
133
|
-
- lib/textus/cli/verb/blame.rb
|
|
134
132
|
- lib/textus/cli/verb/boot.rb
|
|
135
133
|
- lib/textus/cli/verb/build.rb
|
|
136
|
-
- lib/textus/cli/verb/delete.rb
|
|
137
|
-
- lib/textus/cli/verb/deps.rb
|
|
138
134
|
- lib/textus/cli/verb/doctor.rb
|
|
139
135
|
- lib/textus/cli/verb/fetch.rb
|
|
140
|
-
- lib/textus/cli/verb/
|
|
141
|
-
- lib/textus/cli/verb/freshness.rb
|
|
136
|
+
- lib/textus/cli/verb/fetch_all.rb
|
|
142
137
|
- lib/textus/cli/verb/get.rb
|
|
143
138
|
- lib/textus/cli/verb/hook_run.rb
|
|
144
139
|
- lib/textus/cli/verb/hooks.rb
|
|
145
140
|
- lib/textus/cli/verb/init.rb
|
|
146
|
-
- lib/textus/cli/verb/key_delete.rb
|
|
147
|
-
- lib/textus/cli/verb/list.rb
|
|
148
141
|
- lib/textus/cli/verb/mcp_serve.rb
|
|
149
|
-
- lib/textus/cli/verb/migrate.rb
|
|
150
|
-
- lib/textus/cli/verb/mv.rb
|
|
151
|
-
- lib/textus/cli/verb/propose.rb
|
|
152
|
-
- lib/textus/cli/verb/published.rb
|
|
153
|
-
- lib/textus/cli/verb/pulse.rb
|
|
154
142
|
- lib/textus/cli/verb/put.rb
|
|
155
|
-
- lib/textus/cli/verb/rdeps.rb
|
|
156
|
-
- lib/textus/cli/verb/reject.rb
|
|
157
|
-
- lib/textus/cli/verb/retain.rb
|
|
158
|
-
- lib/textus/cli/verb/rule_explain.rb
|
|
159
|
-
- lib/textus/cli/verb/rule_lint.rb
|
|
160
|
-
- lib/textus/cli/verb/rule_list.rb
|
|
161
|
-
- lib/textus/cli/verb/schema.rb
|
|
162
143
|
- lib/textus/cli/verb/schema_diff.rb
|
|
163
144
|
- lib/textus/cli/verb/schema_init.rb
|
|
164
145
|
- lib/textus/cli/verb/schema_migrate.rb
|
|
165
|
-
- lib/textus/cli/verb/uid.rb
|
|
166
|
-
- lib/textus/cli/verb/where.rb
|
|
167
|
-
- lib/textus/cli/verb/zone_mv.rb
|
|
168
146
|
- lib/textus/container.rb
|
|
169
147
|
- lib/textus/contract.rb
|
|
148
|
+
- lib/textus/contract/around.rb
|
|
149
|
+
- lib/textus/contract/binder.rb
|
|
150
|
+
- lib/textus/contract/resources/cursor.rb
|
|
151
|
+
- lib/textus/contract/sources.rb
|
|
152
|
+
- lib/textus/contract/view.rb
|
|
170
153
|
- lib/textus/cursor_store.rb
|
|
171
154
|
- lib/textus/dispatcher.rb
|
|
172
155
|
- lib/textus/doctor.rb
|
|
@@ -303,14 +286,13 @@ files:
|
|
|
303
286
|
- lib/textus/read/doctor.rb
|
|
304
287
|
- lib/textus/read/freshness.rb
|
|
305
288
|
- lib/textus/read/get.rb
|
|
306
|
-
- lib/textus/read/get_or_fetch.rb
|
|
307
289
|
- lib/textus/read/list.rb
|
|
308
|
-
- lib/textus/read/policy_explain.rb
|
|
309
290
|
- lib/textus/read/published.rb
|
|
310
291
|
- lib/textus/read/pulse.rb
|
|
311
292
|
- lib/textus/read/rdeps.rb
|
|
312
293
|
- lib/textus/read/retainable.rb
|
|
313
|
-
- lib/textus/read/
|
|
294
|
+
- lib/textus/read/rule_explain.rb
|
|
295
|
+
- lib/textus/read/rule_list.rb
|
|
314
296
|
- lib/textus/read/schema_envelope.rb
|
|
315
297
|
- lib/textus/read/stale.rb
|
|
316
298
|
- lib/textus/read/uid.rb
|
|
@@ -327,6 +309,7 @@ files:
|
|
|
327
309
|
- lib/textus/uid.rb
|
|
328
310
|
- lib/textus/version.rb
|
|
329
311
|
- lib/textus/write/accept.rb
|
|
312
|
+
- lib/textus/write/build.rb
|
|
330
313
|
- lib/textus/write/delete.rb
|
|
331
314
|
- lib/textus/write/fetch_all.rb
|
|
332
315
|
- lib/textus/write/fetch_events.rb
|
|
@@ -336,7 +319,6 @@ files:
|
|
|
336
319
|
- lib/textus/write/materializer.rb
|
|
337
320
|
- lib/textus/write/mv.rb
|
|
338
321
|
- lib/textus/write/propose.rb
|
|
339
|
-
- lib/textus/write/publish.rb
|
|
340
322
|
- lib/textus/write/put.rb
|
|
341
323
|
- lib/textus/write/reject.rb
|
|
342
324
|
- lib/textus/write/retention_sweep.rb
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Accept < Verb
|
|
5
|
-
command_name "accept"
|
|
6
|
-
|
|
7
|
-
option :as_flag, "--as=ROLE"
|
|
8
|
-
|
|
9
|
-
def call(store)
|
|
10
|
-
key = positional.shift or raise UsageError.new("accept requires a key")
|
|
11
|
-
emit(session_for(store).accept(key))
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Audit < Verb
|
|
5
|
-
command_name "audit"
|
|
6
|
-
|
|
7
|
-
option :key_filter, "--key=KEY"
|
|
8
|
-
option :zone, "--zone=Z"
|
|
9
|
-
option :role_filter, "--role=ROLE"
|
|
10
|
-
option :verb_filter, "--verb=V"
|
|
11
|
-
option :since, "--since=ISO8601|RELATIVE"
|
|
12
|
-
option :seq_since, "--seq-since=N"
|
|
13
|
-
option :correlation_id, "--correlation-id=ID"
|
|
14
|
-
option :limit, "--limit=N"
|
|
15
|
-
|
|
16
|
-
def call(store)
|
|
17
|
-
ops = session_for(store)
|
|
18
|
-
since_time = since && Textus::Read::Audit.parse_since(since, now: Time.now)
|
|
19
|
-
rows = ops.audit(
|
|
20
|
-
key: key_filter,
|
|
21
|
-
zone: zone,
|
|
22
|
-
role: role_filter,
|
|
23
|
-
verb: verb_filter,
|
|
24
|
-
since: since_time,
|
|
25
|
-
seq_since: seq_since&.to_i,
|
|
26
|
-
correlation_id: correlation_id,
|
|
27
|
-
limit: limit&.to_i,
|
|
28
|
-
)
|
|
29
|
-
emit({ "verb" => "audit", "rows" => rows })
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Blame < Verb
|
|
5
|
-
command_name "blame"
|
|
6
|
-
|
|
7
|
-
option :limit, "--limit=N"
|
|
8
|
-
|
|
9
|
-
def call(store)
|
|
10
|
-
key = positional.shift or raise UsageError.new("blame requires a key")
|
|
11
|
-
rows = session_for(store).blame(key: key, limit: limit&.to_i)
|
|
12
|
-
emit({ "verb" => "blame", "key" => key, "rows" => rows })
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Delete < Verb
|
|
5
|
-
command_name "delete"
|
|
6
|
-
|
|
7
|
-
option :as_flag, "--as=ROLE"
|
|
8
|
-
option :if_etag, "--if-etag=E"
|
|
9
|
-
|
|
10
|
-
def call(store)
|
|
11
|
-
key = positional.shift or raise UsageError.new("delete requires a key")
|
|
12
|
-
emit(session_for(store).delete(key, if_etag: if_etag))
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
data/lib/textus/cli/verb/deps.rb
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Deps < Verb
|
|
5
|
-
command_name "deps"
|
|
6
|
-
|
|
7
|
-
def call(store)
|
|
8
|
-
key = positional.shift or raise UsageError.new("deps requires a key")
|
|
9
|
-
emit({ "key" => key, "deps" => session_for(store).deps(key) })
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Freshness < Verb
|
|
5
|
-
command_name "freshness"
|
|
6
|
-
|
|
7
|
-
option :prefix, "--prefix=KEY"
|
|
8
|
-
option :zone, "--zone=Z"
|
|
9
|
-
|
|
10
|
-
def call(store)
|
|
11
|
-
rows = session_for(store).freshness(prefix: prefix, zone: zone)
|
|
12
|
-
emit({ "verb" => "freshness", "rows" => rows })
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class KeyDelete < Verb
|
|
5
|
-
command_name "delete"
|
|
6
|
-
parent_group Group::Key
|
|
7
|
-
|
|
8
|
-
option :as_flag, "--as=ROLE"
|
|
9
|
-
option :dry_run, "--dry-run"
|
|
10
|
-
option :prefix, "--prefix"
|
|
11
|
-
|
|
12
|
-
def call(store)
|
|
13
|
-
if prefix
|
|
14
|
-
p = positional.shift or raise UsageError.new("key delete --prefix requires <prefix>")
|
|
15
|
-
emit(session_for(store).key_delete_prefix(prefix: p, dry_run: dry_run || false).to_h)
|
|
16
|
-
else
|
|
17
|
-
key = positional.shift or raise UsageError.new("key delete requires <key>")
|
|
18
|
-
emit(session_for(store).delete(key))
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
data/lib/textus/cli/verb/list.rb
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class List < Verb
|
|
5
|
-
command_name "list"
|
|
6
|
-
|
|
7
|
-
option :prefix, "--prefix=KEY"
|
|
8
|
-
option :zone, "--zone=Z"
|
|
9
|
-
|
|
10
|
-
def call(store)
|
|
11
|
-
emit({ "entries" => session_for(store).list(prefix: prefix, zone: zone) })
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Migrate < Verb
|
|
5
|
-
command_name "migrate"
|
|
6
|
-
|
|
7
|
-
option :as_flag, "--as=ROLE"
|
|
8
|
-
option :dry_run, "--dry-run"
|
|
9
|
-
|
|
10
|
-
def call(store)
|
|
11
|
-
path = positional.shift or raise UsageError.new("migrate requires <plan.yaml>")
|
|
12
|
-
plan_yaml = File.read(path)
|
|
13
|
-
emit(session_for(store).migrate(plan_yaml: plan_yaml, dry_run: dry_run || false).to_h)
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
data/lib/textus/cli/verb/mv.rb
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Mv < Verb
|
|
5
|
-
command_name "mv"
|
|
6
|
-
parent_group Group::Key
|
|
7
|
-
|
|
8
|
-
option :as_flag, "--as=ROLE"
|
|
9
|
-
option :dry_run, "--dry-run"
|
|
10
|
-
option :prefix, "--prefix"
|
|
11
|
-
|
|
12
|
-
def call(store)
|
|
13
|
-
if prefix
|
|
14
|
-
from_p = positional.shift or raise UsageError.new("mv --prefix requires <from-prefix> <to-prefix>")
|
|
15
|
-
to_p = positional.shift or raise UsageError.new("mv --prefix requires <from-prefix> <to-prefix>")
|
|
16
|
-
emit(session_for(store).key_mv_prefix(from_prefix: from_p, to_prefix: to_p,
|
|
17
|
-
dry_run: dry_run || false).to_h)
|
|
18
|
-
else
|
|
19
|
-
old_key = positional.shift or raise UsageError.new("mv requires <old-key> <new-key>")
|
|
20
|
-
new_key = positional.shift or raise UsageError.new("mv requires <old-key> <new-key>")
|
|
21
|
-
emit(session_for(store).mv(old_key, new_key, dry_run: dry_run || false))
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
# Queue a proposal. Mirrors the MCP `propose` tool: resolves the
|
|
5
|
-
# manifest's propose_zone and prefixes the key, so the author does not
|
|
6
|
-
# need to know the queue zone's name. ADR 0036.
|
|
7
|
-
class Propose < Verb
|
|
8
|
-
command_name "propose"
|
|
9
|
-
|
|
10
|
-
option :as_flag, "--as=ROLE"
|
|
11
|
-
option :use_stdin, "--stdin"
|
|
12
|
-
|
|
13
|
-
def call(store)
|
|
14
|
-
rel = positional.shift or raise UsageError.new("propose requires a key")
|
|
15
|
-
raise UsageError.new("propose requires --stdin") unless use_stdin
|
|
16
|
-
|
|
17
|
-
payload = JSON.parse(@stdin.read)
|
|
18
|
-
env = store.as(resolved_role(store)).propose(
|
|
19
|
-
rel,
|
|
20
|
-
meta: payload["_meta"] || {},
|
|
21
|
-
body: payload["body"] || "",
|
|
22
|
-
)
|
|
23
|
-
emit(env.to_h_for_wire)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Pulse < Verb
|
|
5
|
-
command_name "pulse"
|
|
6
|
-
|
|
7
|
-
option :as_flag, "--as=ROLE"
|
|
8
|
-
option :since, "--since=N"
|
|
9
|
-
|
|
10
|
-
def call(store)
|
|
11
|
-
role = resolved_role(store)
|
|
12
|
-
ops = store.as(role)
|
|
13
|
-
|
|
14
|
-
if since
|
|
15
|
-
emit(ops.pulse(since: since.to_i))
|
|
16
|
-
else
|
|
17
|
-
cursors = Textus::CursorStore.new(root: store.root, role: role)
|
|
18
|
-
result = ops.pulse(since: cursors.read)
|
|
19
|
-
cursors.write(result["cursor"])
|
|
20
|
-
emit(result)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Rdeps < Verb
|
|
5
|
-
command_name "rdeps"
|
|
6
|
-
|
|
7
|
-
def call(store)
|
|
8
|
-
key = positional.shift or raise UsageError.new("rdeps requires a key")
|
|
9
|
-
emit({ "key" => key, "rdeps" => session_for(store).rdeps(key) })
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Reject < Verb
|
|
5
|
-
command_name "reject"
|
|
6
|
-
|
|
7
|
-
option :as_flag, "--as=ROLE"
|
|
8
|
-
|
|
9
|
-
def call(store)
|
|
10
|
-
key = positional.shift or raise UsageError.new("reject requires a key")
|
|
11
|
-
emit(session_for(store).reject(key))
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Retain < Verb
|
|
5
|
-
command_name "retain"
|
|
6
|
-
|
|
7
|
-
option :prefix, "--prefix=KEY"
|
|
8
|
-
option :zone, "--zone=Z"
|
|
9
|
-
option :as_flag, "--as=ROLE"
|
|
10
|
-
|
|
11
|
-
def call(store)
|
|
12
|
-
result = session_for(store).retention_sweep(prefix: prefix, zone: zone)
|
|
13
|
-
emit(result)
|
|
14
|
-
result["ok"] ? 0 : 1
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class RuleExplain < Verb
|
|
5
|
-
command_name "explain"
|
|
6
|
-
parent_group Group::Rule
|
|
7
|
-
|
|
8
|
-
def call(store)
|
|
9
|
-
key = positional.shift or raise UsageError.new("policy explain requires a KEY")
|
|
10
|
-
result = session_for(store).policy_explain(key: key)
|
|
11
|
-
emit({ "verb" => "policy_explain" }.merge(result.transform_keys(&:to_s)))
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class RuleLint < Verb
|
|
5
|
-
command_name "lint"
|
|
6
|
-
parent_group Group::Rule
|
|
7
|
-
|
|
8
|
-
option :against, "--against=FILE"
|
|
9
|
-
|
|
10
|
-
def call(store)
|
|
11
|
-
path = against or raise UsageError.new("rule lint --against=FILE required")
|
|
12
|
-
yaml = File.read(path)
|
|
13
|
-
emit(session_for(store).rule_lint(candidate_yaml: yaml).to_h)
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class RuleList < Verb
|
|
5
|
-
command_name "list"
|
|
6
|
-
parent_group Group::Rule
|
|
7
|
-
|
|
8
|
-
def call(store)
|
|
9
|
-
policies = store.manifest.rules.blocks.map do |b|
|
|
10
|
-
row = { "match" => b.match }
|
|
11
|
-
if b.fetch
|
|
12
|
-
row["fetch"] = {
|
|
13
|
-
"ttl_seconds" => b.fetch.ttl_seconds,
|
|
14
|
-
"on_stale" => b.fetch.on_stale,
|
|
15
|
-
"sync_budget_ms" => b.fetch.sync_budget_ms,
|
|
16
|
-
"fetch_timeout_seconds" => b.fetch.fetch_timeout_seconds,
|
|
17
|
-
}
|
|
18
|
-
end
|
|
19
|
-
row["handler_allowlist"] = b.handler_allowlist.handlers if b.handler_allowlist
|
|
20
|
-
row["guard"] = b.guard if b.guard
|
|
21
|
-
row["retention"] = { "expire_after" => b.retention.expire_after, "archive_after" => b.retention.archive_after } if b.retention
|
|
22
|
-
row
|
|
23
|
-
end
|
|
24
|
-
emit({ "verb" => "policy_list", "policies" => policies })
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
module Textus
|
|
2
|
-
class CLI
|
|
3
|
-
class Verb
|
|
4
|
-
class Schema < Verb
|
|
5
|
-
command_name "show"
|
|
6
|
-
parent_group Group::Schema
|
|
7
|
-
|
|
8
|
-
def call(store)
|
|
9
|
-
key = positional.shift or raise UsageError.new("schema requires a key")
|
|
10
|
-
emit(session_for(store).schema(key))
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|