@codyswann/lisa 4.69.4 → 4.70.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.
- package/all/copy-overwrite/scripts/lib/history-secret-git.mjs +212 -0
- package/all/copy-overwrite/scripts/lib/history-secret-policy.mjs +39 -0
- package/all/copy-overwrite/scripts/lib/history-secret-scanner.mjs +353 -0
- package/all/copy-overwrite/scripts/lisa-gates.mjs +26 -10
- package/all/copy-overwrite/scripts/lisa-history-secrets.mjs +122 -0
- package/all/copy-overwrite/scripts/lisa-rails-prepush.mjs +90 -0
- package/cdk/create-only/stryker.conf.json +2 -0
- package/cdk/package-lisa/package.lisa.json +10 -6
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +46 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/lisa.d.ts +17 -3
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +74 -21
- package/dist/core/lisa.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/plugin-command.d.ts +21 -0
- package/dist/core/plugin-command.d.ts.map +1 -0
- package/dist/core/plugin-command.js +121 -0
- package/dist/core/plugin-command.js.map +1 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +54 -18
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/migrations/ensure-required-history-secret-gate.d.ts +19 -0
- package/dist/migrations/ensure-required-history-secret-gate.d.ts.map +1 -0
- package/dist/migrations/ensure-required-history-secret-gate.js +94 -0
- package/dist/migrations/ensure-required-history-secret-gate.js.map +1 -0
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +3 -0
- package/dist/migrations/index.js.map +1 -1
- package/eslint-plugin-component-structure/package.json +3 -0
- package/expo/create-only/stryker.conf.json +2 -0
- package/expo/package-lisa/package.lisa.json +3 -3
- package/harper-fabric/package-lisa/package.lisa.json +7 -7
- package/nestjs/package-lisa/package.lisa.json +2 -2
- package/package.json +28 -19
- package/phaser/package-lisa/package.lisa.json +7 -7
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/rails/copy-overwrite/.rubocop.yml +0 -2
- package/rails/copy-overwrite/Gemfile.lisa +8 -8
- package/rails/copy-overwrite/lefthook.yml +2 -1
- package/rails/create-only/.simplecov +16 -14
- package/rails/create-only/spec/spec_helper.rb +2 -0
- package/scripts/two-channel-couplings.json +31 -7
- package/scripts/verify-npm-advisories-4333.mjs +166 -0
- package/scripts/verify-rails-tooling.rb +175 -0
- package/typescript/copy-overwrite/.prettierignore +2 -0
- package/typescript/create-only/stryker.conf.json +2 -0
- package/typescript/package-lisa/package.lisa.json +10 -6
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Run with the consumer bundle, Ruby 3.4, and an empty owned scratch directory:
|
|
4
|
+
# bundle exec ruby scripts/verify-rails-tooling.rb MODE TEMPLATE_ROOT SCRATCH
|
|
5
|
+
# Modes: bounds, configuration, coverage, coverage-negative,
|
|
6
|
+
# coverage-line-negative, matchers, matchers-negative, security,
|
|
7
|
+
# security-negative, lint, lint-negative, helper-lint.
|
|
8
|
+
# This bounded probe never boots Rails or connects to a database. The packaged
|
|
9
|
+
# Rails/MySQL journey remains a separate acceptance check.
|
|
10
|
+
require "fileutils"
|
|
11
|
+
require "json"
|
|
12
|
+
|
|
13
|
+
SELECTED = {
|
|
14
|
+
"brakeman" => "8.1.0",
|
|
15
|
+
"database_consistency" => "3.0.14",
|
|
16
|
+
"rack-mini-profiler" => "5.0.0",
|
|
17
|
+
"rspec-rails" => "8.0.4",
|
|
18
|
+
"rubocop-capybara" => "3.0.0",
|
|
19
|
+
"rubocop-yard" => "1.3.0",
|
|
20
|
+
"shoulda-matchers" => "8.0.1",
|
|
21
|
+
"simplecov" => "1.3.2"
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
mode, template_root, scratch = ARGV
|
|
25
|
+
abort "Expected MODE TEMPLATE_ROOT SCRATCH" unless ARGV.length == 3
|
|
26
|
+
template_root = File.realpath(template_root)
|
|
27
|
+
scratch = File.realpath(scratch)
|
|
28
|
+
abort "Scratch must be empty" unless Dir.children(scratch).empty?
|
|
29
|
+
|
|
30
|
+
def copy_template(root, relative, destination)
|
|
31
|
+
FileUtils.mkdir_p(File.dirname(destination))
|
|
32
|
+
FileUtils.cp(File.join(root, relative), destination)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Dir.chdir(scratch) do
|
|
36
|
+
case mode
|
|
37
|
+
when "bounds"
|
|
38
|
+
require "bundler"
|
|
39
|
+
definition = Bundler::Dsl.evaluate(File.join(template_root, "rails/copy-overwrite/Gemfile.lisa"), nil, {})
|
|
40
|
+
failures = SELECTED.filter_map do |name, selected|
|
|
41
|
+
dependency = definition.dependencies.find { |item| item.name == name }
|
|
42
|
+
abort "Missing family #{name}" unless dependency
|
|
43
|
+
actual = Gem.loaded_specs.fetch(name).version
|
|
44
|
+
abort "Wrong selected version #{name}: #{actual}" unless actual.to_s == selected
|
|
45
|
+
next_major = Gem::Version.new("#{actual.segments.first + 1}.0.0")
|
|
46
|
+
abort "Untested next major admitted for #{name}" if dependency.requirement.satisfied_by?(next_major)
|
|
47
|
+
"#{name}: #{dependency.requirement} rejects #{actual}" unless dependency.requirement.satisfied_by?(actual)
|
|
48
|
+
end
|
|
49
|
+
abort failures.join("\n") unless failures.empty?
|
|
50
|
+
{ "shoulda-matchers" => "8.0.0", "simplecov" => "1.3.1" }.each do |name, old_patch|
|
|
51
|
+
requirement = definition.dependencies.find { |item| item.name == name }.requirement
|
|
52
|
+
abort "Pre-fix patch admitted for #{name}" if requirement.satisfied_by?(Gem::Version.new(old_patch))
|
|
53
|
+
end
|
|
54
|
+
puts JSON.generate(marker: "RAILS_TOOL_BOUNDS_ACCEPTED", versions: SELECTED)
|
|
55
|
+
when "configuration"
|
|
56
|
+
copy_template(template_root, "rails/create-only/.simplecov", ".simplecov")
|
|
57
|
+
require "simplecov/no_defaults"
|
|
58
|
+
require "simplecov"
|
|
59
|
+
SimpleCov.deprecations :raise
|
|
60
|
+
load ".simplecov"
|
|
61
|
+
abort "Configuration must not start coverage" if Coverage.running?
|
|
62
|
+
puts "SIMPLECOV_CONFIGURATION_ACCEPTED"
|
|
63
|
+
when "coverage", "coverage-negative", "coverage-line-negative"
|
|
64
|
+
copy_template(template_root, "rails/create-only/.simplecov", ".simplecov")
|
|
65
|
+
copy_template(template_root, "rails/create-only/spec/spec_helper.rb", "spec/spec_helper.rb")
|
|
66
|
+
FileUtils.mkdir_p("app/models")
|
|
67
|
+
File.write("app/models/coverage_probe.rb", <<~RUBY)
|
|
68
|
+
class CoverageProbe
|
|
69
|
+
def greeting(value)
|
|
70
|
+
if value == :hello
|
|
71
|
+
"welcome"
|
|
72
|
+
else
|
|
73
|
+
"goodbye"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
def detail
|
|
77
|
+
text = "detail"
|
|
78
|
+
text.upcase
|
|
79
|
+
text.reverse
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
RUBY
|
|
83
|
+
require "rspec/core"
|
|
84
|
+
load "spec/spec_helper.rb"
|
|
85
|
+
SimpleCov.deprecations :raise
|
|
86
|
+
abort "Coverage must start in the helper" unless Coverage.running?
|
|
87
|
+
SimpleCov.merging false
|
|
88
|
+
require File.join(scratch, "app/models/coverage_probe")
|
|
89
|
+
probe = CoverageProbe.new
|
|
90
|
+
abort "Wrong exercised result" unless probe.greeting(:hello) == "welcome"
|
|
91
|
+
if mode != "coverage-negative"
|
|
92
|
+
abort "Wrong second branch" unless probe.greeting(:other) == "goodbye"
|
|
93
|
+
end
|
|
94
|
+
abort "Wrong line-control result" unless probe.detail == "liated" if mode == "coverage"
|
|
95
|
+
puts "COVERAGE_PROBE_EXECUTED"
|
|
96
|
+
when "matchers", "matchers-negative"
|
|
97
|
+
copy_template(template_root, "rails/create-only/.simplecov", ".simplecov")
|
|
98
|
+
copy_template(template_root, "rails/create-only/spec/spec_helper.rb", "spec/spec_helper.rb")
|
|
99
|
+
FileUtils.mkdir_p("app/models")
|
|
100
|
+
FileUtils.mkdir_p("spec/models")
|
|
101
|
+
File.write("app/models/matcher_probe.rb", <<~RUBY)
|
|
102
|
+
class MatcherProbe
|
|
103
|
+
include ActiveModel::Model
|
|
104
|
+
attr_accessor :name
|
|
105
|
+
#{'validates :name, presence: true' if mode == "matchers"}
|
|
106
|
+
end
|
|
107
|
+
RUBY
|
|
108
|
+
File.write("spec/models/matcher_probe_spec.rb", <<~RUBY)
|
|
109
|
+
require "spec_helper"
|
|
110
|
+
require "active_model"
|
|
111
|
+
require "shoulda/matchers"
|
|
112
|
+
Shoulda::Matchers.configure do |config|
|
|
113
|
+
config.integrate do |with|
|
|
114
|
+
with.test_framework :rspec
|
|
115
|
+
with.library :active_model
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
require File.join(Dir.pwd, "app/models/matcher_probe")
|
|
119
|
+
RSpec.describe MatcherProbe, type: :model do
|
|
120
|
+
it { is_expected.to validate_presence_of(:name) }
|
|
121
|
+
end
|
|
122
|
+
RUBY
|
|
123
|
+
require "rspec/core"
|
|
124
|
+
exit RSpec::Core::Runner.run(["--format", "documentation", "spec/models/matcher_probe_spec.rb"])
|
|
125
|
+
when "security", "security-negative"
|
|
126
|
+
FileUtils.mkdir_p(["app/controllers", "app/models", "config"])
|
|
127
|
+
File.write("Gemfile", "source 'https://rubygems.org'\ngem 'rails', '= 8.1.4'\n")
|
|
128
|
+
File.write("config/application.rb", "require 'rails/all'\nmodule ToolingProbe\nclass Application < Rails::Application\nconfig.load_defaults 8.1\nend\nend\n")
|
|
129
|
+
File.write("config/routes.rb", "Rails.application.routes.draw { resources :probe_records }\n")
|
|
130
|
+
File.write("app/controllers/application_controller.rb", "class ApplicationController < ActionController::Base\nend\n")
|
|
131
|
+
File.write("app/models/probe_record.rb", "class ProbeRecord < ActiveRecord::Base\nend\n")
|
|
132
|
+
query = if mode == "security-negative"
|
|
133
|
+
'ProbeRecord.where("name = \'#{params[:name]}\'")'
|
|
134
|
+
else
|
|
135
|
+
"ProbeRecord.where(name: params[:name])"
|
|
136
|
+
end
|
|
137
|
+
File.write("app/controllers/probe_records_controller.rb", "class ProbeRecordsController < ApplicationController\n def index\n #{query}\n end\nend\n")
|
|
138
|
+
require "brakeman"
|
|
139
|
+
tracker = Brakeman.run(app_path: scratch, quiet: true, print_report: false, run_checks: ["CheckSQL"])
|
|
140
|
+
abort "No SQL check executed" unless tracker.checks.checks_run.include?("SQL")
|
|
141
|
+
abort "No model/controller inspected" if tracker.models.empty? || tracker.controllers.empty?
|
|
142
|
+
warnings = tracker.checks.all_warnings.select { |warning| warning.warning_type == "SQL Injection" }
|
|
143
|
+
puts JSON.generate(marker: "BRAKEMAN_SQL_CONTROL", checks: tracker.checks.checks_run, warnings: warnings.length, models: tracker.models.length, controllers: tracker.controllers.length)
|
|
144
|
+
exit(warnings.empty? ? 0 : 1)
|
|
145
|
+
when "helper-lint"
|
|
146
|
+
copy_template(template_root, "rails/copy-overwrite/.rubocop.yml", ".rubocop.yml")
|
|
147
|
+
[".rubocop_todo.yml", "rubocop.thresholds.yml", ".rubocop.local.yml"].each do |name|
|
|
148
|
+
copy_template(template_root, "rails/create-only/#{name}", name)
|
|
149
|
+
end
|
|
150
|
+
["spec/spec_helper.rb", "spec/rails_helper.rb"].each do |name|
|
|
151
|
+
copy_template(template_root, "rails/create-only/#{name}", name)
|
|
152
|
+
end
|
|
153
|
+
require "rubocop"
|
|
154
|
+
exit RuboCop::CLI.new.run(["--format", "json", "--cache", "false", "spec/spec_helper.rb", "spec/rails_helper.rb"])
|
|
155
|
+
when "lint", "lint-negative"
|
|
156
|
+
copy_template(template_root, "rails/copy-overwrite/.rubocop.yml", ".rubocop.yml")
|
|
157
|
+
[".rubocop_todo.yml", "rubocop.thresholds.yml", ".rubocop.local.yml"].each do |name|
|
|
158
|
+
copy_template(template_root, "rails/create-only/#{name}", name)
|
|
159
|
+
end
|
|
160
|
+
FileUtils.mkdir_p("spec/features")
|
|
161
|
+
negative = mode == "lint-negative"
|
|
162
|
+
File.write("spec/features/tooling_probe_spec.rb", <<~RUBY)
|
|
163
|
+
#{negative ? 'all(".thing").first' : 'find(".thing")'}
|
|
164
|
+
|
|
165
|
+
# @param #{negative ? "wrong" : "name"} [String] the name
|
|
166
|
+
def greeting(name)
|
|
167
|
+
name
|
|
168
|
+
end
|
|
169
|
+
RUBY
|
|
170
|
+
require "rubocop"
|
|
171
|
+
exit RuboCop::CLI.new.run(["--only", "Capybara/FindAllFirst,YARD/MismatchName", "--format", "json", "--cache", "false", "spec/features/tooling_probe_spec.rb"])
|
|
172
|
+
else
|
|
173
|
+
abort "Unknown mode #{mode}"
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -86,9 +86,11 @@ scripts/lisa-destructive-guard.mjs
|
|
|
86
86
|
scripts/lisa-environment-prepare.mjs
|
|
87
87
|
scripts/lisa-floor-collisions.mjs
|
|
88
88
|
scripts/lisa-gates.mjs
|
|
89
|
+
scripts/lisa-history-secrets.mjs
|
|
89
90
|
scripts/lisa-lint-staged-preflight.mjs
|
|
90
91
|
scripts/lisa-mutation.mjs
|
|
91
92
|
scripts/lisa-postinstall.mjs
|
|
93
|
+
scripts/lisa-rails-prepush.mjs
|
|
92
94
|
scripts/lisa-reconcile-policy.mjs
|
|
93
95
|
scripts/lisa-run-gates.mjs
|
|
94
96
|
scripts/lisa-schema-validate.mjs
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
|
|
3
3
|
"testRunner": "vitest",
|
|
4
|
+
"_pluginsComment": "Resolve the declared runner explicitly for isolated dependency layouts instead of relying on sibling package discovery.",
|
|
5
|
+
"plugins": ["@stryker-mutator/vitest-runner"],
|
|
4
6
|
"reporters": ["clear-text", "progress", "html"],
|
|
5
7
|
"coverageAnalysis": "perTest",
|
|
6
8
|
"ignoreStatic": true,
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"typecheck:lisa": "node scripts/lib/worktree-dependencies.mjs && tsc --noEmit"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"eslint-plugin-oxlint": "
|
|
35
|
-
"oxlint": "
|
|
34
|
+
"eslint-plugin-oxlint": "1.62.0",
|
|
35
|
+
"oxlint": "1.62.0",
|
|
36
36
|
"oxlint-tsgolint": "^0.24.0",
|
|
37
37
|
"@stryker-mutator/core": "^9.0.0",
|
|
38
38
|
"@stryker-mutator/vitest-runner": "^9.0.0",
|
|
@@ -49,7 +49,9 @@
|
|
|
49
49
|
"vite": "^8.3.2",
|
|
50
50
|
"ws": ">=8.21.0",
|
|
51
51
|
"form-data": ">=4.0.6",
|
|
52
|
-
"systeminformation": ">=5.31.7"
|
|
52
|
+
"systeminformation": ">=5.31.7",
|
|
53
|
+
"qs": "^6.16.0",
|
|
54
|
+
"deepmerge-ts": "^8.0.1"
|
|
53
55
|
},
|
|
54
56
|
"overrides": {
|
|
55
57
|
"@isaacs/brace-expansion": "^5.0.1",
|
|
@@ -62,16 +64,18 @@
|
|
|
62
64
|
"vite": "^8.3.2",
|
|
63
65
|
"ws": ">=8.21.0",
|
|
64
66
|
"form-data": ">=4.0.6",
|
|
65
|
-
"systeminformation": ">=5.31.7"
|
|
67
|
+
"systeminformation": ">=5.31.7",
|
|
68
|
+
"qs": "^6.16.0",
|
|
69
|
+
"deepmerge-ts": "^8.0.1"
|
|
66
70
|
}
|
|
67
71
|
},
|
|
68
72
|
"defaults": {
|
|
69
73
|
"devDependencies": {
|
|
70
74
|
"@ast-grep/cli": "^0.40.4",
|
|
71
75
|
"@vitest/coverage-v8": "^4.1.11",
|
|
72
|
-
"eslint": "^9.39.
|
|
76
|
+
"eslint": "^9.39.5",
|
|
73
77
|
"husky": "^8.0.0",
|
|
74
|
-
"prettier": "
|
|
78
|
+
"prettier": "3.8.0",
|
|
75
79
|
"typescript": "^6.0.3",
|
|
76
80
|
"vitest": "^4.1.11"
|
|
77
81
|
},
|