-
Notifications
You must be signed in to change notification settings - Fork 5
Casting plane adoption + injectrc seal wave (T07, T14) #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2eaa83c
aabd8b1
ec9d8e9
0017352
cc73385
727ba7e
55f9893
16cc2d5
a1fba84
652c2a7
6004ca2
d5beea8
4dacb99
77e7637
a98a5b7
54494f6
07740f6
d863ab2
fa6fe71
3ddd86a
277525d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| root = true | ||
|
|
||
| [*] | ||
| charset = utf-8 | ||
| end_of_line = lf | ||
| insert_final_newline = true | ||
| trim_trailing_whitespace = true | ||
| indent_style = space | ||
| indent_size = 4 | ||
|
|
||
| [*.{kt,kts}] | ||
| # Line-length ceiling 300: the standard across these projects. A generous | ||
| # ceiling so the gate fires only on genuinely unreadable lines. Note ktlint | ||
| # cannot auto-fix an over-long line (it will not break it for you), so a line | ||
| # past 300 must be wrapped by hand — rare at this ceiling. | ||
| max_line_length = 300 | ||
| # Non-auto-fixable comment-placement rules: ktlint flags these but will not fix | ||
| # them, so they cannot belong to a deterministic auto-format gate. Both guard | ||
| # legitimate, readable patterns (labelled Java-interop bool args; an explanatory | ||
| # comment on a single-line if-guard). Comment placement is a sign-plane (review) | ||
| # concern, not a bump-plane (auto-fix) one. | ||
| ktlint_standard_comment-wrapping = disabled | ||
| ktlint_standard_if-else-wrapping = disabled | ||
|
|
||
| [*.{c,cc,cpp,h,hpp}] | ||
| indent_size = 2 | ||
|
|
||
| [*.{yml,yaml,toml,json}] | ||
| indent_size = 2 | ||
|
|
||
| [*.md] | ||
| trim_trailing_whitespace = false |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #!/bin/sh | ||
| # Mold casting hook: the fast structural gate (gatesFast) on commit. | ||
| # A convenience pre-check, never the wall: `--no-verify` walks past this, the | ||
| # release build does not (ADR-0002). gatesFast also runs on every variant build. | ||
| set -e | ||
| if [ -x ./gradlew ]; then | ||
| exec ./gradlew gatesFast --quiet | ||
| fi | ||
| echo "mold pre-commit: no ./gradlew found; skipping gatesFast" >&2 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #!/bin/sh | ||
| # Mold casting hook: the full wall (gatesFull) on push. | ||
| # A convenience pre-check, never the wall: `--no-verify` walks past this, the | ||
| # release build does not (ADR-0002). gatesFull also binds at assembleRelease / | ||
| # bundleRelease. Inert where there is no push target (local-only developer). | ||
| set -e | ||
| if [ -x ./gradlew ]; then | ||
| exec ./gradlew gatesFull --quiet | ||
| fi | ||
| echo "mold pre-push: no ./gradlew found; skipping gatesFull" >&2 |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,6 +23,32 @@ jobs: | |||||||||
| - name: Tests | ||||||||||
| run: cargo test -p resetprop | ||||||||||
|
|
||||||||||
| gates: | ||||||||||
| name: Casting wall (fmt, clippy, supply, comment-hygiene) | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
| steps: | ||||||||||
| - uses: actions/checkout@v4 | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n .github/workflows/ci.yml | head -50Repository: Enginex0/resetprop-rs Length of output: 1528 🌐 Web query:
💡 Result: Securing GitHub Actions workflows involves two critical best practices: pinning actions to immutable commit SHAs and properly managing credential persistence. Pinning Actions to Commit SHAs Using version tags (e.g., Citations:
Pin third-party actions to commit SHAs and disable checkout credential persistence. Lines 30 and 42 use mutable action version tags ( Suggested fix- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false- - name: Install cargo-deny
- uses: taiki-e/install-action@v2
+ - name: Install cargo-deny
+ uses: taiki-e/install-action@<commit-sha> # v2📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.25.2)[warning] 30-30: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [error] 30-30: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||
|
|
||||||||||
| - name: Resolve pinned toolchain (rust-toolchain.toml) | ||||||||||
| run: rustup show | ||||||||||
|
|
||||||||||
| - name: Format | ||||||||||
| run: cargo fmt --all --check | ||||||||||
|
|
||||||||||
| - name: Clippy (workspace, all targets and features) | ||||||||||
| run: cargo clippy --all-targets --all-features -- -D warnings | ||||||||||
|
|
||||||||||
| - name: Install cargo-deny | ||||||||||
| uses: taiki-e/install-action@v2 | ||||||||||
| with: | ||||||||||
| tool: cargo-deny | ||||||||||
|
|
||||||||||
| - name: Supply line (offline, deterministic) | ||||||||||
| run: cargo deny check licenses bans sources | ||||||||||
|
|
||||||||||
| - name: Comment hygiene | ||||||||||
| run: python3 scripts/comment-hygiene.py | ||||||||||
|
|
||||||||||
| cross-compile: | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
| strategy: | ||||||||||
|
|
@@ -32,10 +58,10 @@ jobs: | |||||||||
| steps: | ||||||||||
| - uses: actions/checkout@v4 | ||||||||||
|
|
||||||||||
| - name: Install Rust | ||||||||||
| uses: dtolnay/rust-toolchain@stable | ||||||||||
| with: | ||||||||||
| targets: ${{ matrix.target }} | ||||||||||
| - name: Pinned toolchain + Android target | ||||||||||
| run: | | ||||||||||
| rustup show | ||||||||||
| rustup target add ${{ matrix.target }} | ||||||||||
|
|
||||||||||
| - name: Install NDK | ||||||||||
| uses: nttld/setup-ndk@v1 | ||||||||||
|
|
@@ -51,16 +77,3 @@ jobs: | |||||||||
|
|
||||||||||
| - name: Build ${{ matrix.target }} | ||||||||||
| run: cargo build --release --target ${{ matrix.target }} | ||||||||||
|
|
||||||||||
| clippy: | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
| steps: | ||||||||||
| - uses: actions/checkout@v4 | ||||||||||
|
|
||||||||||
| - name: Install Rust | ||||||||||
| uses: dtolnay/rust-toolchain@stable | ||||||||||
| with: | ||||||||||
| components: clippy | ||||||||||
|
|
||||||||||
| - name: Clippy (library) | ||||||||||
| run: cargo clippy -p resetprop -- -D warnings | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 0.1.13 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,22 @@ | ||
| plan: resetprop-rs-injectrc-ports | ||
| updated: 2026-06-17 | ||
| updated: 2026-06-18 | ||
| tasks: | ||
| T01: done | ||
| T02: done | ||
| T03: done | ||
| T04: done | ||
| T05: done | ||
| T06: backlog | ||
| T07: backlog | ||
| T08: backlog | ||
| T09: backlog | ||
| T10: backlog | ||
| T06: done | ||
| T07: done | ||
| T08: done | ||
| T09: done | ||
| T10: done | ||
| T11: cut | ||
| T12: done | ||
| T13: done | ||
| T14: backlog | ||
| T14: done | ||
| T15: done | ||
| T16: done | ||
| T17: backlog | ||
| T18: backlog | ||
| T17: done | ||
| T18: done | ||
| T19: done |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // Generated by tools/cast.py. VERSION-PIN LOCATION #2 of 2: the convention jar so | ||
| // the project's convention plugins can apply mold.kotlin-quality and mold.gates by | ||
| // id. Keep in lockstep with the root build's pin (both == castingVersion). | ||
| plugins { | ||
| `kotlin-dsl` | ||
| } | ||
|
|
||
| dependencies { | ||
| // The mold casting law. The AGP/Kotlin gradlePlugin deps below let Gradle | ||
| // generate the type-safe plugin accessors the convention plugins use. | ||
| implementation("mold.casting:convention:0.1.13") | ||
| // implementation(libs.android.gradlePlugin) | ||
| // implementation(libs.kotlin.gradlePlugin) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // Generated by tools/cast.py. build-logic is a standalone included build, so it | ||
| // does NOT inherit the root's repositories or version catalog: the law repo is wired | ||
| // here SECOND (miss it -> "Could not find mold.casting:convention"), and the same | ||
| // gradle/libs.versions.toml is imported by path so the catalog stays one SSOT. | ||
| dependencyResolutionManagement { | ||
| repositories { | ||
| maven { url = uri("file:///mnt/companion/president/maven-casting") } // mold casting law repo | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Parameterize the Casting Maven repo path instead of hard-coding a machine-local mount. Line 7 binds plugin resolution to Suggested direction- maven { url = uri("file:///mnt/companion/president/maven-casting") }
+ val castingRepo = providers.gradleProperty("castingRepoUrl")
+ .orElse(System.getenv("CASTING_REPO_URL") ?: "")
+ .get()
+ require(castingRepo.isNotBlank()) { "Missing casting repo URL. Set -PcastingRepoUrl or CASTING_REPO_URL." }
+ maven { url = uri(castingRepo) }🤖 Prompt for AI Agents |
||
| gradlePluginPortal() | ||
| google() | ||
| mavenCentral() | ||
| } | ||
| versionCatalogs { | ||
| create("libs") { | ||
| from(files("../gradle/libs.versions.toml")) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| rootProject.name = "build-logic" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| // Generated by tools/cast.py (the Casting plane). | ||
| plugins { | ||
| id("mold.rust-gates") version "0.1.13" | ||
| id("mold.comment-hygiene") version "0.1.13" | ||
| } | ||
|
|
||
| // The module-edge dependency guard has NO published plugin (the one gate that is | ||
| // project-authored): cast.py emits the task + matrix parser here. Fill in | ||
| // gradle/dependency-guard.config with your tier matrix; an illegal edge then fails | ||
| // `check` (-> build), not just a review. See casting-adoption.md. | ||
| tasks.register("dependencyGuard") { | ||
| group = "verification" | ||
| description = "Fails any project->project edge outside gradle/dependency-guard.config." | ||
| val matrixFile = file("gradle/dependency-guard.config") | ||
| val modules = subprojects | ||
| doLast { | ||
| val matrix = DependencyMatrix.parse(matrixFile.readText()) | ||
| val violations = modules.flatMap { module -> | ||
| module.configurations | ||
| .flatMap { it.dependencies } | ||
| .filterIsInstance<ProjectDependency>() | ||
| .map { it.path } | ||
| .distinct() | ||
| .filter { it != module.path } | ||
| .filterNot { matrix.permits(module.path, it) } | ||
| .map { "${module.path} -> $it" } | ||
| }.distinct().sorted() | ||
| if (violations.isNotEmpty()) { | ||
| throw GradleException( | ||
| "Dependency guard: ${violations.size} edge(s) outside the matrix:\n" + | ||
| violations.joinToString("\n") { " $it" }, | ||
| ) | ||
| } | ||
| logger.lifecycle("Dependency guard: ${modules.size} modules, every edge within the matrix.") | ||
| } | ||
| } | ||
|
|
||
| subprojects { | ||
| tasks.matching { it.name == "check" }.configureEach { | ||
| dependsOn(rootProject.tasks.named("dependencyGuard")) | ||
| } | ||
| } | ||
|
|
||
| // A contract target matches face-precise (contract:state); any other by bare tier. | ||
| class DependencyMatrix(private val allowed: Map<String, Set<String>>) { | ||
| fun permits(source: String, target: String): Boolean { | ||
| val targetSegments = target.split(":").filter { it.isNotEmpty() } | ||
| val spec = if (targetSegments.firstOrNull() == "contract" && targetSegments.size >= 2) { | ||
| "contract:${targetSegments[1]}" | ||
| } else { | ||
| targetSegments.firstOrNull().orEmpty() | ||
| } | ||
| return spec in (allowed[tierOf(source)] ?: emptySet()) | ||
| } | ||
|
|
||
| private fun tierOf(path: String): String = | ||
| path.split(":").firstOrNull { it.isNotEmpty() }.orEmpty() | ||
|
|
||
| companion object { | ||
| fun parse(text: String): DependencyMatrix { | ||
| val allowed = text.lineSequence() | ||
| .map { it.substringBefore('#').trim() } | ||
| .filter { it.isNotEmpty() } | ||
| .associate { line -> | ||
| require("->" in line) { "dependency-guard.config: rule has no '->': `$line`" } | ||
| val tier = line.substringBefore("->").trim() | ||
| val specs = line.substringAfter("->").trim() | ||
| .split(Regex("\\s+")).filter { it.isNotEmpty() }.toSet() | ||
| tier to specs | ||
| } | ||
| return DependencyMatrix(allowed) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Cross-wire the cargo-root rust gates into each module's wall: the cargo root is a | ||
| // plain project, so rust-gates' in-plugin fold finds no local gatesFast/Full; this | ||
| // binding makes a broken crate fail the same wall (enforcement.md, ADR-0010). | ||
| subprojects { | ||
| tasks.matching { it.name == "gatesFast" } | ||
| .configureEach { dependsOn(rootProject.tasks.named("rustGatesFast")) } | ||
| tasks.matching { it.name == "gatesFull" } | ||
| .configureEach { dependsOn(rootProject.tasks.named("rustGatesFull")) } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Casting-plane detekt config — the WHOLE active rule set, not an override. | ||
| # The mold.kotlin-quality convention plugin sets buildUponDefaultConfig = false, | ||
| # so detekt's 200-rule default set is OFF and only the rules turned on below run. | ||
| # | ||
| # enforcement.md scopes this gate to two things and nothing else: | ||
| # - swallowed / empty / over-generic exceptions (bump) | ||
| # - a LargeClass / LongMethod hard ceiling (bump at the ceiling only) | ||
| # The soft size budget is a sign-plane (judgment) concern, not a deterministic | ||
| # gate, so detekt enforces only the hard ceiling here. Formatting belongs to | ||
| # Spotless/ktlint, never detekt — no formatting or style rules live in this file. | ||
| # | ||
| # Per ADR-0007 (certainty over severity): gate only what we are certain about. | ||
| # Widening this set is an ADR plus a canary promotion, not an edit. | ||
|
|
||
| # EmptyCatchBlock is in detekt's empty-blocks ruleset, not exceptions. | ||
| empty-blocks: | ||
| active: true | ||
| EmptyCatchBlock: | ||
| active: true | ||
|
|
||
| exceptions: | ||
| active: true | ||
| SwallowedException: | ||
| active: true | ||
| TooGenericExceptionCaught: | ||
| active: true | ||
|
|
||
| complexity: | ||
| active: true | ||
| LargeClass: | ||
| active: true | ||
| threshold: 600 | ||
| LongMethod: | ||
| active: true | ||
| threshold: 60 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "_comment": "Casting-plane JVM license allowlist read by the first-party checkLicense gate in mold.jvm-supply: an external dependency whose POM license matches none of these regexes fails gatesFull. Mirrors the deny.toml policy for the Rust half. A dependency whose license the gate cannot read directly (e.g. declared only in a parent POM) is frozen with a per-module entry ({ \"moduleName\": \"group:artifact\" }) — the brownfield mechanism. Widening the license SET (not a per-module freeze) is an ADR plus a canary promotion.", | ||
| "allowedLicenses": [ | ||
| { "moduleLicense": ".*Apache.*" }, | ||
| { "moduleLicense": ".*MIT.*" }, | ||
| { "moduleLicense": ".*BSD.*" }, | ||
| { "moduleLicense": ".*ISC.*" }, | ||
| { "moduleLicense": ".*Unicode.*" }, | ||
| { "moduleLicense": ".*CC0.*" }, | ||
| { "moduleLicense": ".*Zlib.*" }, | ||
| { "moduleLicense": ".*Public Domain.*" } | ||
| ] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set explicit least-privilege permissions for the new
gatesjob.The new job currently inherits default token permissions. Declare read-only scope explicitly to avoid accidental write-capable defaults.
Suggested fix
gates: name: Casting wall (fmt, clippy, supply, comment-hygiene) runs-on: ubuntu-latest + permissions: + contents: read steps:📝 Committable suggestion
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 26-50: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block
(excessive-permissions)
🤖 Prompt for AI Agents
Source: Linters/SAST tools