Skip to content

Commit ddf38b1

Browse files
Reject corrupt MST/2 verified facts and preserve raw content (#31)
* fix(git): respect shallow depth and v0 negotiation boundaries * test(redis): accept OS-assigned standalone ports * test(s3): allow isolated RustFS integration endpoints * fix(git): preserve SSH shallow negotiation and isolate test ports * Validate MST2 verified facts and preserve raw blob content * Isolate retention lifecycle test runtime * ci: run isolated Linux repository gates on pull requests * ci: avoid duplicate case-insensitive workflow environment keys * ci: handle generated future lint and retain failed gate cache * feat(mst2): index fixed namespace bindings by path components (#40) * feat(mst2): add fixed namespace component index * test(mst2): keep namespace oracle inside private domain * test(mst2): register internal namespace regression suite
1 parent 40b0ef9 commit ddf38b1

12 files changed

Lines changed: 2167 additions & 80 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
name: Repository gates
2+
3+
on:
4+
pull_request:
5+
workflow_dispatch:
6+
7+
permissions:
8+
contents: read
9+
10+
concurrency:
11+
group: repository-gates-${{ github.event.pull_request.number || github.ref }}
12+
cancel-in-progress: true
13+
14+
jobs:
15+
linux:
16+
name: Linux repository gates
17+
runs-on: ubuntu-latest
18+
timeout-minutes: 120
19+
env:
20+
CARGO_TERM_COLOR: always
21+
CARGO_INCREMENTAL: "0"
22+
CARGO_BUILD_JOBS: "2"
23+
CARGO_PROFILE_DEV_DEBUG: "0"
24+
CARGO_PROFILE_TEST_DEBUG: "0"
25+
RUST_BACKTRACE: "1"
26+
NO_PROXY: localhost,127.0.0.1,::1,host.docker.internal
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- name: Install system dependencies
31+
run: |
32+
sudo apt-get update
33+
sudo apt-get install -y pkg-config libssl-dev protobuf-compiler
34+
35+
- uses: dtolnay/rust-toolchain@nightly
36+
with:
37+
components: rustfmt
38+
39+
- uses: dtolnay/rust-toolchain@stable
40+
with:
41+
components: clippy
42+
43+
- uses: Swatinem/rust-cache@v2
44+
with:
45+
save-if: "true"
46+
47+
- name: Check formatting
48+
run: cargo +nightly fmt --all --check
49+
50+
- name: Check all targets and features
51+
run: cargo clippy --all-targets --all-features -- -D warnings
52+
53+
- name: Build
54+
run: cargo build
55+
56+
- name: Build tests
57+
run: cargo build --tests
58+
59+
- name: Start isolated test dependencies
60+
shell: bash
61+
run: |
62+
set -euo pipefail
63+
source scripts/lib/mega2-it.sh
64+
mega2_it_ensure_env_test
65+
mega2_it_prepare_git_workdir
66+
docker compose -p mega2-it -f docker/docker-compose.test.yml --profile git \
67+
up -d --build --wait postgres redis rustfs rustfs-init git-cli
68+
69+
- name: Run repository tests with test environment
70+
shell: bash
71+
run: |
72+
set -euo pipefail
73+
source .env.test
74+
export no_proxy="$NO_PROXY"
75+
cargo test --all
76+
77+
- name: Stop isolated test dependencies
78+
if: always()
79+
run: docker compose -p mega2-it -f docker/docker-compose.test.yml --profile git down -v

‎src/callisto/mst2_verified_object.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
//!
33
//! One row per verified object: Git identity + raw content digest + 64-bit
44
//! size + verification state. The natural key is
5-
//! `(storage_domain, git_oid, object_kind)`; rows are insert-only with
6-
//! ON CONFLICT DO NOTHING — a row only ever appears after the content was
7-
//! fetched and hashed by this service (write-through verification).
5+
//! `(storage_domain, git_oid, object_kind)`. Current-generation facts retain
6+
//! first-write-wins semantics; valid legacy facts can be atomically upgraded
7+
//! only after this service fetches and hashes the raw body again.
88
99
use sea_orm::entity::prelude::*;
1010
use serde::{Deserialize, Serialize};

‎src/ceres/pack/import_repo.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,10 @@ impl RepoHandler for ImportRepo {
452452
}
453453
}
454454

455+
#[allow(
456+
clippy::double_must_use,
457+
reason = "async_recursion adds must_use to the generated boxed Future"
458+
)]
455459
#[async_recursion]
456460
pub(crate) async fn collect_git_blob_filepaths(
457461
storage: GitDbStorage,

‎src/ceres/snapshot/error.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ pub enum SnapshotErrorCode {
3434
DigestMismatch,
3535
RangeNotSupported,
3636
SymlinkTraversal,
37+
ObjectUnavailable,
38+
IntegrityError,
3739
Internal,
3840
}
3941

@@ -60,6 +62,8 @@ impl SnapshotErrorCode {
6062
SnapshotErrorCode::DigestMismatch => "EXPECTED_DIGEST_MISMATCH",
6163
SnapshotErrorCode::RangeNotSupported => "RANGE_NOT_SUPPORTED",
6264
SnapshotErrorCode::SymlinkTraversal => "SYMLINK_TRAVERSAL",
65+
SnapshotErrorCode::ObjectUnavailable => "OBJECT_UNAVAILABLE",
66+
SnapshotErrorCode::IntegrityError => "INTEGRITY_ERROR",
6367
SnapshotErrorCode::Internal => "INTERNAL",
6468
}
6569
}
@@ -79,6 +83,7 @@ impl SnapshotErrorCode {
7983
| SnapshotErrorCode::PathNotFound
8084
| SnapshotErrorCode::LeaseUnknown => 404,
8185
SnapshotErrorCode::SnapshotNotReady => 503,
86+
SnapshotErrorCode::ObjectUnavailable => 503,
8287
SnapshotErrorCode::NotDirectory
8388
| SnapshotErrorCode::Conflict
8489
| SnapshotErrorCode::CursorStale
@@ -87,6 +92,7 @@ impl SnapshotErrorCode {
8792
SnapshotErrorCode::UnsupportedEntry => 422,
8893
SnapshotErrorCode::LimitExceeded | SnapshotErrorCode::ProofBudgetExceeded => 413,
8994
SnapshotErrorCode::LeaseExpired | SnapshotErrorCode::SnapshotGone => 410,
95+
SnapshotErrorCode::IntegrityError => 502,
9096
SnapshotErrorCode::Internal => 500,
9197
}
9298
}

‎src/ceres/snapshot/mod.rs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
//! MST/2 snapshot domain (spec 02/03): fixed views over pinned Git trees.
22
//!
3-
//! Slice scope (T02-a): native monorepo views only — no bindings, imports or
4-
//! release policy yet (T04/T05). Everything here resolves against fixed OIDs;
5-
//! no code path in this module may read current refs.
3+
//! Serving remains native-only. The independent namespace index is an unwired
4+
//! composition seam; identity, attestation and publication integration remain
5+
//! separate gates. Fixed-source readers must never look up current refs.
66
pub mod chunks;
77
pub mod descriptor;
88
pub mod error;
99
pub mod frame_stream;
10+
pub mod namespace;
1011
pub mod pages;
1112
pub mod publication;
1213
pub mod resolver;

0 commit comments

Comments
 (0)