hecks 3.12.0 → 3.13.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/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/meta_validator/syntax_boot.rb +16 -12
- data/lib/hecks/bluebook/meta_validator.rb +28 -21
- data/lib/hecks/deploy/bluebook/deploy.bluebook +1 -1
- 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/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/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/site/bluebook/site.bluebook +16 -1
- 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/{verdicts-df19f35868d3284a70f55e42dcef87ef4e65e6a678e5135f72e1f6cff4c1357b.json → verdicts-48318ca172edd21443b1ad02801c697fff100b746e828f09db987647641a5df2.json} +1 -1
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/src/auth.rs +58 -0
- data/rust/host/src/platform_signin/session.rs +1 -1
- metadata +21 -7
- /data/lib/hecks/framework/{oidc.json → compliance.oidc.json} +0 -0
- /data/lib/hecks/grammar/{oidc.json → expression.oidc.json} +0 -0
- /data/prebuilt/{d74a00e996222c1d8b676d5959092effc46b4dc59e0555f3bf9554ac58e3094a.marshal → 2b59737fbdbd5f44edda0fddce2611f45d76087b3a7c782d1f1a17ea58c77948.marshal} +0 -0
- /data/prebuilt/{9ee54e2f0d4d6d3fe046827779b221e02de665fba911a048ae5dd8b8fbfb7d90.marshal → 58208399bada10b0db99928c48e38789288fc58f7b71a72b21bfa386680e32ed.marshal} +0 -0
|
@@ -60,7 +60,8 @@ module Hecks
|
|
|
60
60
|
|
|
61
61
|
# @param registry [Runtime::Registry] a registry holding the Site chapter
|
|
62
62
|
# @return [Hash{Symbol => Array<String>}] each constrained field to its allowed values, and
|
|
63
|
-
# `:http_method` to the verbs a route may answer
|
|
63
|
+
# `:http_method` to the verbs a route may answer and `:edge_function_kind` to the kinds of
|
|
64
|
+
# `EdgeFunction` row
|
|
64
65
|
# @raise [Invalid] when the registry does not hold the Site chapter
|
|
65
66
|
def self.vocabulary(registry)
|
|
66
67
|
site = registry.bluebook("Site") or
|
|
@@ -69,7 +70,8 @@ module Hecks
|
|
|
69
70
|
members = lambda do |name|
|
|
70
71
|
route.value_objects.find { |object| object.hecks_name == name }.members.map { |member| member.fetch(:value) }
|
|
71
72
|
end
|
|
72
|
-
RowBuilder::VOCABULARY.transform_values(&members)
|
|
73
|
+
closed = RowBuilder::VOCABULARY.transform_values(&members)
|
|
74
|
+
closed.merge(http_method: members.call("HttpMethod"), edge_function_kind: members.call("EdgeFunctionKind"))
|
|
73
75
|
end
|
|
74
76
|
|
|
75
77
|
# @param chapter [Bluebook::Chapter] a chapter to search
|
|
@@ -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"]
|
|
@@ -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