hecks 3.12.0 → 3.14.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.
- checksums.yaml +4 -4
- data/examples/pizzas/bluebook/pizzas.bluebook +4 -4
- data/lib/hecks/adapters/driven/script_runner.adapter +3 -0
- data/lib/hecks/adapters/driven/script_runner.rb +93 -0
- data/lib/hecks/adapters/driven.rb +1 -0
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +15 -5
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +16 -12
- data/lib/hecks/bluebook/meta_validator.rb +28 -21
- data/lib/hecks/bluebook/named_pattern.rb +33 -0
- data/lib/hecks/bluebook.rb +1 -0
- data/lib/hecks/cli/domain_stub.rb +1 -1
- data/lib/hecks/cli/interview_aggregate.rb +4 -4
- data/lib/hecks/deploy/bluebook/deploy.bluebook +35 -35
- data/lib/hecks/framework/bluebook/change.behaviors +30 -0
- data/lib/hecks/framework/bluebook/change.bluebook +162 -0
- data/lib/hecks/framework/bluebook/change.hecksagon +21 -0
- data/lib/hecks/framework/change.oidc.json +34 -0
- data/lib/hecks/framework/console_settings.oidc.json +103 -0
- data/lib/hecks/framework/governance.oidc.json +28 -0
- data/lib/hecks/framework/identity.oidc.json +18 -0
- data/lib/hecks/framework/privacy.oidc.json +30 -0
- data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +1 -1
- data/lib/hecks/gate/stages.yml +3 -0
- data/lib/hecks/grammar/translation.oidc.json +48 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +12 -1
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +2 -1
- data/lib/hecks/hecks/codebase.bluebook +37 -37
- data/lib/hecks/hecks/custodian.bluebook +14 -14
- data/lib/hecks/hecks/hecks.bluebook +2 -2
- data/lib/hecks/hecks/rehearsal.bluebook +3 -3
- data/lib/hecks/hecks/tooling.bluebook +22 -22
- data/lib/hecks/language/bluebook/aggregate.bluebook +1 -0
- data/lib/hecks/language/bluebook/command.bluebook +1 -0
- data/lib/hecks/language/bluebook/entity.bluebook +1 -0
- data/lib/hecks/language/bluebook/query.bluebook +1 -0
- data/lib/hecks/language/bluebook/shape.bluebook +8 -7
- data/lib/hecks/language/hecksagon/port_operation.bluebook +1 -0
- data/lib/hecks/projections/deploy/fargate/cdn/lines.rb +12 -1
- data/lib/hecks/projections/site/admin_cms/templates/membership.rb +10 -7
- data/lib/hecks/projections/site/edge/behaviours.rb +10 -6
- data/lib/hecks/projections/site/edge/checks.rb +2 -0
- data/lib/hecks/projections/site/edge/function_checks.rb +104 -0
- data/lib/hecks/projections/site/edge/function_code.rb +86 -0
- data/lib/hecks/projections/site/edge/redirect_host.js.tmpl +65 -0
- data/lib/hecks/projections/site/edge.rb +35 -9
- data/lib/hecks/projections/site/site_cdn.rb +21 -7
- data/lib/hecks/projections/site/table/row_builder.rb +12 -2
- data/lib/hecks/projections/site/table.rb +4 -2
- data/lib/hecks/quality_control/quality_control.bluebook +51 -51
- data/lib/hecks/site/bluebook/site.bluebook +21 -6
- data/lib/hecks/sme/bluebook/sme.bluebook +12 -12
- data/lib/hecks/tickets/bluebook/tickets.bluebook +3 -3
- data/lib/hecks/tools/oidc_manifests.rb +44 -6
- data/lib/hecks/tools/site_routes/templates.rb +13 -9
- data/lib/hecks/version.rb +1 -1
- data/prebuilt/{d74a00e996222c1d8b676d5959092effc46b4dc59e0555f3bf9554ac58e3094a.marshal → 1a6f596be124228be93eba1d86dbc9d2933190fa389b284331241cb9f27115a0.marshal} +0 -0
- data/prebuilt/{9ee54e2f0d4d6d3fe046827779b221e02de665fba911a048ae5dd8b8fbfb7d90.marshal → a883a7e568667aa5ac904c82daff356bdf9e996252a36af6def4a4a43efb967e.marshal} +0 -0
- data/prebuilt/verdicts-872993b1aa26d73fe48f28251374b8585fed145d02aab42be0f00de386b6ff80.json +1 -0
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/src/auth.rs +58 -0
- data/rust/host/src/payments/roles.rs +159 -0
- data/rust/host/src/payments/tests.rs +25 -0
- data/rust/host/src/payments.rs +20 -11
- data/rust/host/src/platform_signin/session.rs +1 -1
- data/rust/parser/src/build/mod.rs +1 -0
- data/rust/parser/src/build/named_pattern.rs +23 -0
- data/rust/parser/src/keywords.rs +6 -0
- data/rust/parser/src/parse/mod.rs +22 -1
- metadata +24 -7
- data/prebuilt/verdicts-df19f35868d3284a70f55e42dcef87ef4e65e6a678e5135f72e1f6cff4c1357b.json +0 -1
- /data/lib/hecks/framework/{oidc.json → compliance.oidc.json} +0 -0
- /data/lib/hecks/grammar/{oidc.json → expression.oidc.json} +0 -0
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
# The same command projects the CDN: a project that adds Edge, EdgePolicy, EdgeOrigin and EdgeRule rows
|
|
13
13
|
# to its chapter has the CloudFront behaviours and the listener rules written into the marked regions
|
|
14
14
|
# of the template it owns (the `:site_cdn` projection). Those rows are the template's facts, so only the
|
|
15
|
-
# closed sets they draw on, cache class and
|
|
15
|
+
# closed sets they draw on, cache class, origin and the kind of an EdgeFunction row, are named here. A
|
|
16
|
+
# route's `edge:` names an EdgeFunction row, a viewer-request function the projection writes into the
|
|
17
|
+
# template's `edge_functions` region and attaches to that route's behaviour.
|
|
16
18
|
#
|
|
17
19
|
# Each run records that it was requested before the SiteToolchain port is asked, and what came of
|
|
18
20
|
# it after. No command declares a role: the chapter boots standing alone.
|
|
@@ -33,6 +35,7 @@ Hecks.bluebook "Site" do
|
|
|
33
35
|
attribute :source, Source, optional: true
|
|
34
36
|
attribute :http_method, HttpMethod, optional: true
|
|
35
37
|
attribute :preview, Preview, optional: true
|
|
38
|
+
attribute :edge, EdgeName, optional: true
|
|
36
39
|
|
|
37
40
|
# `/blog/:slug.html` names a parameter; a trailing `/*` matches everything beneath a prefix. A
|
|
38
41
|
# row with a `command:` or `query:` source may leave its path out, and the projection derives it
|
|
@@ -78,6 +81,18 @@ Hecks.bluebook "Site" do
|
|
|
78
81
|
attribute :value, String, one_of: ["public", "draft"]
|
|
79
82
|
end
|
|
80
83
|
|
|
84
|
+
# The logical id of an `EdgeFunction` row: the viewer-request function the route's behaviour runs.
|
|
85
|
+
value_object "EdgeName" do
|
|
86
|
+
attribute :value, String, pattern: '\A[A-Za-z][A-Za-z0-9]*\z'
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# What an `EdgeFunction` row asks the projection to write: `redirect_host` answers a request for
|
|
90
|
+
# a watched path on an alias host with a redirect to the canonical host and leaves every other
|
|
91
|
+
# request alone.
|
|
92
|
+
value_object "EdgeFunctionKind" do
|
|
93
|
+
attribute :value, String, one_of: ["redirect_host"]
|
|
94
|
+
end
|
|
95
|
+
|
|
81
96
|
# The HTTP verbs a route answers.
|
|
82
97
|
value_object "HttpMethod" do
|
|
83
98
|
attribute :value, String, one_of: ["GET", "POST", "PUT", "PATCH", "DELETE"]
|
|
@@ -114,14 +129,14 @@ Hecks.bluebook "Site" do
|
|
|
114
129
|
identified_by :run
|
|
115
130
|
|
|
116
131
|
value_object "RunKey" do
|
|
117
|
-
attribute :value, String,
|
|
132
|
+
attribute :value, String, matches: :present
|
|
118
133
|
|
|
119
134
|
invariant("a run is named") { !value.to_s.empty? }
|
|
120
135
|
end
|
|
121
136
|
|
|
122
137
|
# A project directory, whose `bluebook/` holds the chapter that declares the route table.
|
|
123
138
|
value_object "DomainPath" do
|
|
124
|
-
attribute :value, String,
|
|
139
|
+
attribute :value, String, matches: :not_empty
|
|
125
140
|
|
|
126
141
|
invariant("a project is named by its path") { !value.to_s.empty? }
|
|
127
142
|
end
|
|
@@ -129,7 +144,7 @@ Hecks.bluebook "Site" do
|
|
|
129
144
|
# A directory or file anywhere on disk, relative to where the command runs: where routes.ts is
|
|
130
145
|
# written when not in the project's generated/ directory, or the template to rewrite in place.
|
|
131
146
|
value_object "Location" do
|
|
132
|
-
attribute :value, String,
|
|
147
|
+
attribute :value, String, matches: :not_empty
|
|
133
148
|
end
|
|
134
149
|
|
|
135
150
|
# The file extension of the generated module: `ts` (routes.ts), or `mts` (routes.mts), which
|
|
@@ -149,12 +164,12 @@ Hecks.bluebook "Site" do
|
|
|
149
164
|
|
|
150
165
|
# Path patterns, comma separated: the behaviours a change is about to add to the live distribution.
|
|
151
166
|
value_object "PathList" do
|
|
152
|
-
attribute :value, String,
|
|
167
|
+
attribute :value, String, matches: :not_empty
|
|
153
168
|
end
|
|
154
169
|
|
|
155
170
|
# Policy references and the ids they stand for live, as `!Ref Name=id`, comma separated.
|
|
156
171
|
value_object "PolicyRefs" do
|
|
157
|
-
attribute :value, String,
|
|
172
|
+
attribute :value, String, matches: :not_empty
|
|
158
173
|
end
|
|
159
174
|
|
|
160
175
|
# A running site's address, `https://example.org`: what `check_site` sends its requests to.
|
|
@@ -30,37 +30,37 @@ Hecks.bluebook "SME" do
|
|
|
30
30
|
attribute :accepted_actions, Tally
|
|
31
31
|
|
|
32
32
|
value_object "Reference" do
|
|
33
|
-
attribute :value, String,
|
|
33
|
+
attribute :value, String, matches: :present
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
# The domain being discovered, spelled as its bluebook will spell it. Many interviews, with
|
|
37
37
|
# different experts on different days, name the same subject; the domain is not modelled here.
|
|
38
38
|
value_object "Subject" do
|
|
39
|
-
attribute :value, String,
|
|
39
|
+
attribute :value, String, matches: :present
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
# Who is being interviewed.
|
|
43
43
|
value_object "Expert" do
|
|
44
|
-
attribute :value, String,
|
|
44
|
+
attribute :value, String, matches: :not_empty
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
value_object "Question" do
|
|
48
|
-
attribute :value, String,
|
|
48
|
+
attribute :value, String, matches: :not_empty
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
# The expert's answer in their own words.
|
|
52
52
|
value_object "Answer" do
|
|
53
|
-
attribute :value, String,
|
|
53
|
+
attribute :value, String, matches: :not_empty
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# A label for grouping exchanges ("lending rules"); optional on every exchange.
|
|
57
57
|
value_object "Topic" do
|
|
58
|
-
attribute :value, String,
|
|
58
|
+
attribute :value, String, matches: :not_empty
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
value_object "Exchange" do
|
|
62
|
-
attribute :question, String,
|
|
63
|
-
attribute :answer, String,
|
|
62
|
+
attribute :question, String, matches: :not_empty
|
|
63
|
+
attribute :answer, String, matches: :not_empty
|
|
64
64
|
attribute :topic, String, optional: true
|
|
65
65
|
end
|
|
66
66
|
|
|
@@ -76,7 +76,7 @@ Hecks.bluebook "SME" do
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
value_object "Name" do
|
|
79
|
-
attribute :value, String,
|
|
79
|
+
attribute :value, String, matches: :present
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
# How many findings of a kind were accepted.
|
|
@@ -86,7 +86,7 @@ Hecks.bluebook "SME" do
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
value_object "Statement" do
|
|
89
|
-
attribute :value, String,
|
|
89
|
+
attribute :value, String, matches: :not_empty
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
# Whether an action brings its thing into being, as opposed to happening to one that exists.
|
|
@@ -97,12 +97,12 @@ Hecks.bluebook "SME" do
|
|
|
97
97
|
# A list the expert gave in a breath, comma separated: the values a field may take, or the
|
|
98
98
|
# fields an action needs to be told. Absent when the expert gave none.
|
|
99
99
|
value_object "Listing" do
|
|
100
|
-
attribute :value, String,
|
|
100
|
+
attribute :value, String, matches: :not_empty
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
# Who may do an action, in the expert's words ("a maintainer", "QA engineer").
|
|
104
104
|
value_object "Actor" do
|
|
105
|
-
attribute :value, String,
|
|
105
|
+
attribute :value, String, matches: :not_empty
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
# A thing the domain keeps track of, and the field that identifies one: an aggregate to be.
|
|
@@ -32,7 +32,7 @@ Hecks.bluebook "Tickets" do
|
|
|
32
32
|
identified_by :finding
|
|
33
33
|
|
|
34
34
|
value_object "FindingKey" do
|
|
35
|
-
attribute :value, String,
|
|
35
|
+
attribute :value, String, matches: :present
|
|
36
36
|
|
|
37
37
|
invariant("a finding is named") { !value.to_s.empty? }
|
|
38
38
|
end
|
|
@@ -65,7 +65,7 @@ Hecks.bluebook "Tickets" do
|
|
|
65
65
|
# The same finding refiled by the QA loop carries the same fingerprint, so a report of it while an
|
|
66
66
|
# open finding holds it changes nothing.
|
|
67
67
|
value_object "Fingerprint" do
|
|
68
|
-
attribute :value, String,
|
|
68
|
+
attribute :value, String, matches: :present
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
value_object "Number" do
|
|
@@ -239,7 +239,7 @@ Hecks.bluebook "Tickets" do
|
|
|
239
239
|
end
|
|
240
240
|
|
|
241
241
|
value_object "FindingKey" do
|
|
242
|
-
attribute :value, String,
|
|
242
|
+
attribute :value, String, matches: :present
|
|
243
243
|
end
|
|
244
244
|
|
|
245
245
|
lifecycle :status, default: "draft" do
|
|
@@ -6,7 +6,8 @@ require_relative "../tools"
|
|
|
6
6
|
module Hecks
|
|
7
7
|
module Tools
|
|
8
8
|
# Projects each domain's OIDC client and scope manifest (`Hecks::Projections::OIDC`) into an
|
|
9
|
-
# `oidc.json` beside the domain.
|
|
9
|
+
# `oidc.json` beside the domain, or into one `<chapter>.oidc.json` for each chapter of a
|
|
10
|
+
# directory that holds several.
|
|
10
11
|
#
|
|
11
12
|
# A domain that has no bluebook is skipped and one that cannot be projected is reported, so a
|
|
12
13
|
# sweep over the whole checkout carries on past either. `hecks deploy
|
|
@@ -45,20 +46,57 @@ module Hecks
|
|
|
45
46
|
.uniq.sort
|
|
46
47
|
end
|
|
47
48
|
|
|
49
|
+
# Projects one manifest for each chapter the directory holds.
|
|
50
|
+
#
|
|
48
51
|
# @param root [String] the checkout
|
|
49
52
|
# @param path [String] a domain directory, relative to `root`
|
|
50
53
|
# @return [void]
|
|
51
54
|
def project(root, path)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return warn(" #{path}: no bluebook found — skipped") unless name
|
|
55
|
+
registry = Hecks.boot(File.join(root, path), install_driving: false).registry
|
|
56
|
+
return warn(" #{path}: no bluebook found — skipped") if registry.bluebooks.empty?
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
puts " #{path}/oidc.json <- #{name}"
|
|
58
|
+
project_chapters(registry, root, path)
|
|
58
59
|
rescue StandardError => e
|
|
59
60
|
warn " #{path}: cannot project — #{e.message.lines.first.strip}"
|
|
60
61
|
end
|
|
61
62
|
|
|
63
|
+
# The chapters a directory declares: those with a `.bluebook` file under it. A chapter it
|
|
64
|
+
# only attaches (Governance, for one) is loaded from elsewhere and has its own directory's
|
|
65
|
+
# manifest.
|
|
66
|
+
#
|
|
67
|
+
# @param registry [Hecks::Runtime::Registry] the booted registry of the directory
|
|
68
|
+
# @param directory [String] the directory that was booted
|
|
69
|
+
# @return [Array<String>] the chapter names, in load order; the first loaded when none has a
|
|
70
|
+
# recorded source
|
|
71
|
+
def chapters_of(registry, directory)
|
|
72
|
+
under = "#{File.expand_path(directory)}/"
|
|
73
|
+
own = registry.bluebooks.keys.select do |name|
|
|
74
|
+
Array(registry.bluebook_sources[name]).any? { |source| File.expand_path(source).start_with?(under) }
|
|
75
|
+
end
|
|
76
|
+
own.empty? ? registry.bluebooks.keys.first(1) : own
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# @param registry [Hecks::Runtime::Registry] the booted registry of the directory
|
|
80
|
+
# @param root [String] the checkout
|
|
81
|
+
# @param path [String] the domain directory, relative to `root`
|
|
82
|
+
# @return [void]
|
|
83
|
+
def project_chapters(registry, root, path)
|
|
84
|
+
names = chapters_of(registry, File.join(root, path))
|
|
85
|
+
names.each do |name|
|
|
86
|
+
file = file_for(names, name)
|
|
87
|
+
write_manifest(registry, name, File.join(root, path, file))
|
|
88
|
+
puts " #{path}/#{file} <- #{name}"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# A domain of one chapter keeps `oidc.json`; a directory of several chapters, such as the
|
|
93
|
+
# framework members, gets one manifest each, so none of them stands for the others.
|
|
94
|
+
#
|
|
95
|
+
# @param names [Array<String>] every chapter the directory holds
|
|
96
|
+
# @param name [String] the chapter the manifest is for
|
|
97
|
+
# @return [String] the manifest's file name: `oidc.json`, or `<chapter>.oidc.json`
|
|
98
|
+
def file_for(names, name) = names.one? ? "oidc.json" : "#{Naming.snake(name)}.oidc.json"
|
|
99
|
+
|
|
62
100
|
# @param registry [Hecks::Runtime::Registry] the booted registry
|
|
63
101
|
# @param name [String] the bluebook to project
|
|
64
102
|
# @param out [String] where the manifest goes
|
|
@@ -27,22 +27,19 @@ module Hecks
|
|
|
27
27
|
regions = Projector.call(:site_cdn, bluebook: site.chapter, options: { table: site.table, edge: edge })
|
|
28
28
|
relative = template || edge.setting.template
|
|
29
29
|
source = template_source(root, template, relative)
|
|
30
|
-
text = rewritten(File.read(source), regions, relative
|
|
30
|
+
text = rewritten(File.read(source), regions, relative)
|
|
31
31
|
{ destination(source, out, template, relative) => text }
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
# @param text [String] the template
|
|
35
35
|
# @param regions [Hash{String => String}] each region's name to the block that goes in it
|
|
36
36
|
# @param relative [String] the template's name, for a message
|
|
37
|
-
# @param edge [Projections::Site::Edge] the checked edge
|
|
38
37
|
# @return [String] the template with each region rewritten
|
|
39
|
-
# @raise [SystemExit] when a region is missing, or a listener_rules
|
|
40
|
-
# by an edge
|
|
41
|
-
def rewritten(text, regions, relative
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"and the Edge row says alb: false; remove the region"
|
|
45
|
-
end
|
|
38
|
+
# @raise [SystemExit] when a region is missing, or a listener_rules or edge_functions region
|
|
39
|
+
# is left behind by an edge that has no load balancer or no EdgeFunction row
|
|
40
|
+
def rewritten(text, regions, relative)
|
|
41
|
+
refuse_leftover(text, regions, relative, "listener_rules", "the Edge row says alb: false")
|
|
42
|
+
refuse_leftover(text, regions, relative, "edge_functions", "the project declares no EdgeFunction rows")
|
|
46
43
|
regions.reduce(text) do |current, (name, block)|
|
|
47
44
|
unless Projections::Site::Regions.region?(current, name)
|
|
48
45
|
abort "project_site: #{relative} has no BEGIN/END GENERATED site_cdn #{name} region"
|
|
@@ -52,6 +49,13 @@ module Hecks
|
|
|
52
49
|
end
|
|
53
50
|
end
|
|
54
51
|
|
|
52
|
+
# Refuses a region the edge does not use, so the stale text in it is removed by hand.
|
|
53
|
+
def refuse_leftover(text, regions, relative, name, reason)
|
|
54
|
+
return if regions.key?(name) || !Projections::Site::Regions.region?(text, name)
|
|
55
|
+
|
|
56
|
+
abort "project_site: #{relative} has a BEGIN/END GENERATED site_cdn #{name} region, and #{reason}; remove the region"
|
|
57
|
+
end
|
|
58
|
+
|
|
55
59
|
# @return [Hash] nothing, after refusing a template named for a project with no edge
|
|
56
60
|
def missing_edge(template)
|
|
57
61
|
abort "project_site: --template names #{template}, but the project declares no Edge rows" if template
|
data/lib/hecks/version.rb
CHANGED
|
Binary file
|