Skip to content

Commit 67e1883

Browse files
authored
Merge pull request #37 from dhawal-ss/beta/production-readiness-2026-08
Bind Phase 2 through 6 implementation to reviewed source
2 parents a3e35bd + 2e10e6f commit 67e1883

490 files changed

Lines changed: 53619 additions & 13010 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
* text=auto eol=lf
2+
mesh/infra/container-prototypes/caddy/patches/*.patch whitespace=-space-before-tab
3+
mesh/infra/container-candidates/caddy/patches/*.patch whitespace=-space-before-tab

.github/CODEOWNERS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
* @dhawal-ss
22

33
# Release publication and its security policy require an owner review.
4+
/.github/workflows/ @dhawal-ss
5+
/.github/dependabot.yml @dhawal-ss
6+
/.github/CODEOWNERS @dhawal-ss
47
/.github/workflows/release-beta.yml @dhawal-ss
58
/.github/workflows/security.yml @dhawal-ss
69
/.github/dependency-review-config.yml @dhawal-ss
10+
/mesh/release/ @dhawal-ss
11+
/mesh/infra/ @dhawal-ss
12+
/mesh/docs/operations/ @dhawal-ss
713
/mesh/scripts/beta-release-preflight.ps1 @dhawal-ss
814
/mesh/scripts/check-matrix-release-dependencies.ps1 @dhawal-ss
915
/mesh/scripts/rust-dependency-policy.json @dhawal-ss

.github/dependabot.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,50 @@ updates:
4545
labels:
4646
- dependencies
4747
- rust
48+
49+
- package-ecosystem: npm
50+
directory: /mesh/feature-deps/matrix-voice
51+
schedule:
52+
interval: weekly
53+
day: monday
54+
time: "08:35"
55+
timezone: America/Chicago
56+
open-pull-requests-limit: 3
57+
labels: [dependencies, matrix-voice]
58+
59+
- package-ecosystem: npm
60+
directory: /mesh/feature-deps/legacy-lan
61+
schedule:
62+
interval: weekly
63+
day: monday
64+
time: "08:40"
65+
timezone: America/Chicago
66+
open-pull-requests-limit: 3
67+
labels: [dependencies, legacy-lan]
68+
69+
- package-ecosystem: docker
70+
directory: /mesh/infra/homeserver
71+
schedule:
72+
interval: weekly
73+
day: monday
74+
time: "08:45"
75+
timezone: America/Chicago
76+
labels: [dependencies, containers, homeserver]
77+
78+
- package-ecosystem: docker
79+
directory: /mesh/infra/matrixrtc
80+
schedule:
81+
interval: weekly
82+
day: monday
83+
time: "08:50"
84+
timezone: America/Chicago
85+
labels: [dependencies, containers, matrixrtc]
86+
87+
- package-ecosystem: docker
88+
directory: /mesh/infra/matrix-spike
89+
schedule:
90+
interval: weekly
91+
day: monday
92+
time: "08:55"
93+
timezone: America/Chicago
94+
labels: [dependencies, containers, matrix-spike]

.github/workflows/ci.yml

Lines changed: 102 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ on:
88

99
env:
1010
CARGO_TERM_COLOR: always
11+
MESH_MATRIX_VOICE_FRONTEND: matrix-voice
1112

1213
permissions:
14+
actions: read
1315
contents: read
1416

1517
jobs:
@@ -21,7 +23,7 @@ jobs:
2123
matrix:
2224
os: [ubuntu-latest, windows-latest]
2325
steps:
24-
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
26+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
2527

2628
- name: Install Rust toolchain
2729
uses: dtolnay/rust-toolchain@d0befba8b9ddf874327619e84c39b094edd58b66 # 1.93.0
@@ -41,7 +43,7 @@ jobs:
4143
libsqlcipher-dev
4244
4345
- name: Cache cargo registry & build
44-
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
46+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
4547
with:
4648
path: |
4749
~/.cargo/registry
@@ -74,11 +76,17 @@ jobs:
7476
working-directory: mesh/src-tauri
7577
run: cargo test --no-default-features --features matrix-backend --locked --jobs 1
7678

79+
- name: Check and test signed-candidate Matrix voice backend
80+
working-directory: mesh/src-tauri
81+
run: |
82+
cargo check --no-default-features --features matrix-voice --locked --jobs 1
83+
cargo test --no-default-features --features matrix-voice --locked --jobs 1
84+
7785
legacy-rust:
7886
name: Legacy LAN Rust
7987
runs-on: ubuntu-latest
8088
steps:
81-
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
89+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
8290

8391
- name: Install Rust toolchain
8492
uses: dtolnay/rust-toolchain@d0befba8b9ddf874327619e84c39b094edd58b66 # 1.93.0
@@ -95,7 +103,7 @@ jobs:
95103
libsqlcipher-dev
96104
97105
- name: Cache cargo registry & legacy build
98-
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
106+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
99107
with:
100108
path: |
101109
~/.cargo/registry
@@ -120,18 +128,21 @@ jobs:
120128
name: Frontend Build & Browser E2E
121129
runs-on: ubuntu-latest
122130
steps:
123-
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
131+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
124132
with:
125133
# The readiness validator binds sourceTreeHash to an exact historical
126134
# sourceCommit, so a synthetic depth-one PR merge is insufficient.
127135
fetch-depth: 0
128136

129137
- name: Setup Node.js
130-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
138+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
131139
with:
132140
node-version: 22
133141
cache: npm
134-
cache-dependency-path: mesh/package-lock.json
142+
cache-dependency-path: |
143+
mesh/package-lock.json
144+
mesh/feature-deps/matrix-voice/package-lock.json
145+
mesh/feature-deps/legacy-lan/package-lock.json
135146
136147
- name: Install dependencies
137148
working-directory: mesh
@@ -157,14 +168,18 @@ jobs:
157168
working-directory: mesh
158169
run: npm run check:icons
159170

171+
- name: Check bundled interface sounds
172+
working-directory: mesh
173+
run: npm run check:interface-sounds
174+
160175
- name: Check reviewed public services
161176
working-directory: mesh
162177
run: npm run check:public-services
163178

164-
- name: Check production readiness ledger
179+
- name: Check protected evidence and production readiness ledger
165180
working-directory: mesh
166181
run: |
167-
node --test scripts/check-readiness-ledger.test.mjs
182+
npm run check:protected-evidence
168183
npm run check:readiness-ledger
169184
170185
- name: Check fail-closed external acceptance contract
@@ -177,6 +192,10 @@ jobs:
177192
working-directory: mesh
178193
run: npm run check:public-site
179194

195+
- name: Check approved owner decisions
196+
working-directory: mesh
197+
run: npm run check:owner-decisions
198+
180199
- name: Check beta product boundary
181200
working-directory: mesh
182201
run: npm run check:beta-contract
@@ -206,13 +225,23 @@ jobs:
206225
working-directory: mesh
207226
run: npm run test -- --maxWorkers=4
208227

209-
- name: Build frontend
228+
- name: Test isolated voice dependency graphs
229+
working-directory: mesh
230+
run: npm run test:voice-features
231+
232+
- name: Build non-shipping comparison frontends
233+
working-directory: mesh
234+
run: |
235+
npm run build:lan
236+
npm run build:matrix
237+
238+
- name: Build signed-candidate Matrix voice frontend
210239
working-directory: mesh
211-
run: npm run build
240+
run: npm run build:matrix-voice
212241

213242
- name: Enforce frontend entry bundle budget
214243
working-directory: mesh
215-
run: npm run check:bundle-size
244+
run: npm run check:bundle-size -- --report release/bundle-report.json
216245

217246
- name: Install Playwright browser
218247
working-directory: mesh
@@ -221,3 +250,64 @@ jobs:
221250
- name: Run browser E2E tests and WCAG scans
222251
working-directory: mesh
223252
run: npm run e2e
253+
254+
protected-evidence:
255+
name: Protected CI evidence manifest
256+
if: always()
257+
needs: [matrix-rust, legacy-rust, check-frontend]
258+
runs-on: ubuntu-latest
259+
steps:
260+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
261+
with:
262+
fetch-depth: 0
263+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
264+
with:
265+
node-version: 22
266+
- name: Fail closed unless every protected job passed
267+
env:
268+
MATRIX_RUST: ${{ needs.matrix-rust.result }}
269+
LEGACY_RUST: ${{ needs.legacy-rust.result }}
270+
FRONTEND: ${{ needs.check-frontend.result }}
271+
run: |
272+
node mesh/scripts/protected-ci-results.mjs
273+
- name: Upload protected CI payload
274+
id: payload
275+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
276+
with:
277+
name: ci-r0-payload-${{ github.sha }}
278+
path: mesh/release/ci-run-results.json
279+
if-no-files-found: error
280+
retention-days: 90
281+
- name: Resolve protected CI payload archive size
282+
id: payload-metadata
283+
env:
284+
GH_TOKEN: ${{ github.token }}
285+
ARTIFACT_ID: ${{ steps.payload.outputs.artifact-id }}
286+
run: echo "size=$(gh api repos/${GITHUB_REPOSITORY}/actions/artifacts/${ARTIFACT_ID} --jq .size_in_bytes)" >> "$GITHUB_OUTPUT"
287+
- name: Generate protected CI evidence manifest
288+
working-directory: mesh
289+
run: |
290+
node scripts/protected-evidence-manifest.mjs \
291+
--source-sha "${{ github.sha }}" \
292+
--tree-hash "$(git rev-parse HEAD^{tree})" \
293+
--workflow-name CI \
294+
--run-id "${{ github.run_id }}" \
295+
--run-attempt "${{ github.run_attempt }}" \
296+
--workflow-uri "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
297+
--payload-path release/ci-run-results.json \
298+
--payload-name ci-r0-payload-${{ github.sha }} \
299+
--payload-uri "${{ steps.payload.outputs.artifact-url }}" \
300+
--payload-digest "${{ steps.payload.outputs.artifact-digest }}" \
301+
--payload-size "${{ steps.payload-metadata.outputs.size }}" \
302+
--command "matrix-rust + legacy-rust + check-frontend protected jobs" \
303+
--build-mode matrix-voice \
304+
--features matrix-voice,legacy-p2p \
305+
--retention-days 90 \
306+
--output release/ci-protected-evidence-manifest.json
307+
- name: Upload protected CI evidence manifest
308+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
309+
with:
310+
name: ci-protected-evidence-${{ github.sha }}
311+
path: mesh/release/ci-protected-evidence-manifest.json
312+
if-no-files-found: error
313+
retention-days: 90
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: Mesh container candidates
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches: [main, beta/production-readiness-2026-08]
7+
paths:
8+
- .github/workflows/container-candidates.yml
9+
- mesh/infra/container-candidates/**
10+
- mesh/scripts/check-container-candidates.mjs
11+
- mesh/scripts/check-container-candidates.test.mjs
12+
- mesh/scripts/check-candidate-container-signature-evidence.mjs
13+
- mesh/scripts/check-candidate-container-signature-evidence.test.mjs
14+
- mesh/scripts/check-registry-tag-movement.mjs
15+
- mesh/scripts/check-registry-tag-movement.test.mjs
16+
- mesh/docs/operations/CONTAINER_CANDIDATE_MAINTENANCE.md
17+
- mesh/package.json
18+
schedule:
19+
- cron: '17 8 * * 1'
20+
21+
concurrency:
22+
group: mesh-container-candidates-${{ github.ref }}
23+
cancel-in-progress: false
24+
25+
permissions:
26+
contents: read
27+
28+
jobs:
29+
verify:
30+
name: Verify Mesh container candidate (${{ matrix.name }})
31+
runs-on: ubuntu-latest
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
include:
36+
- name: caddy
37+
image: ghcr.io/dhawal-ss/mesh-caddy
38+
tag: 2.11.4-mesh.1
39+
digest: sha256:67cf933778f84aadd59f93fc5d2eaf6471df7b415135ae95fc1b1e6e5f4b7e4f
40+
- name: lk-jwt-service
41+
image: ghcr.io/dhawal-ss/mesh-lk-jwt-service
42+
tag: 0.5.0-mesh.2
43+
digest: sha256:78bf2f1e8535928037abc35a9886614b3f722885b54f1f707a570e6991252710
44+
steps:
45+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
46+
with:
47+
persist-credentials: false
48+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
49+
with:
50+
node-version: 22
51+
- name: Validate candidate image policy
52+
working-directory: mesh
53+
run: npm run check:container-candidates
54+
- name: Set up Buildx
55+
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
56+
- name: Resolve exact candidate image
57+
id: exact
58+
shell: bash
59+
run: |
60+
exact_image='${{ matrix.image }}:${{ matrix.tag }}@${{ matrix.digest }}'
61+
docker buildx imagetools inspect "$exact_image" >/dev/null
62+
echo "image=$exact_image" >> "$GITHUB_OUTPUT"
63+
echo "Verified \`$exact_image\`" >> "$GITHUB_STEP_SUMMARY"
64+
- name: Install pinned Cosign
65+
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
66+
with:
67+
cosign-release: v3.0.6
68+
- name: Generate candidate CycloneDX SBOM
69+
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
70+
with:
71+
image: ${{ steps.exact.outputs.image }}
72+
format: cyclonedx-json
73+
syft-version: v1.50.0
74+
output-file: candidate-${{ matrix.name }}.cdx.json
75+
upload-artifact: false
76+
upload-release-assets: false
77+
- name: Reject fixable High or Critical findings
78+
uses: anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # v7.4.0
79+
with:
80+
image: ${{ steps.exact.outputs.image }}
81+
fail-build: true
82+
severity-cutoff: high
83+
only-fixed: true
84+
grype-version: v0.116.1
85+
output-format: json
86+
output-file: candidate-${{ matrix.name }}-grype.json
87+
- name: Bind exact image, SBOM, and scanner database evidence
88+
run: >-
89+
node mesh/scripts/check-container-scan-evidence.mjs
90+
--sbom "candidate-${{ matrix.name }}.cdx.json"
91+
--scan "candidate-${{ matrix.name }}-grype.json"
92+
--image '${{ steps.exact.outputs.image }}'
93+
--scope release
94+
--output "candidate-${{ matrix.name }}-scan-evidence.json"
95+
- name: Verify the Mesh keyless candidate signature
96+
shell: bash
97+
env:
98+
EXACT_IMAGE: ${{ steps.exact.outputs.image }}
99+
run: |
100+
cosign verify \
101+
--certificate-identity-regexp='^https://github\.com/dhawal-ss/mesh/\.github/workflows/container-candidates\.yml@refs/heads/(main|beta/production-readiness-2026-08)$' \
102+
--certificate-oidc-issuer='https://token.actions.githubusercontent.com' \
103+
--output=json \
104+
"$EXACT_IMAGE" > "candidate-${{ matrix.name }}-signature-raw.json"
105+
node mesh/scripts/check-candidate-container-signature-evidence.mjs \
106+
--verification "candidate-${{ matrix.name }}-signature-raw.json" \
107+
--image "$EXACT_IMAGE" \
108+
--output "candidate-${{ matrix.name }}-signature.json"
109+
rm -f "candidate-${{ matrix.name }}-signature-raw.json"
110+
- name: Upload immutable candidate evidence
111+
if: always()
112+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
113+
with:
114+
name: mesh-container-candidate-${{ matrix.name }}-${{ github.sha }}
115+
path: |
116+
candidate-${{ matrix.name }}.cdx.json
117+
candidate-${{ matrix.name }}-grype.json
118+
candidate-${{ matrix.name }}-scan-evidence.json
119+
candidate-${{ matrix.name }}-signature.json
120+
if-no-files-found: error
121+
retention-days: 90

0 commit comments

Comments
 (0)