Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 43 additions & 21 deletions ARCHITECTURE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -245,17 +245,20 @@ mode = "required"
mode = "required"

# sbx-mgr's node-local SQLite database (`sandboxes` and every other sbx-mgr
# table) is opened, migrated and queried only by its store, `src/db` of the
# server crate. Within sbx-mgr's crates, naming rusqlite, opening a
# connection or transaction, using the shared SQLite open and migration
# helpers or the shared job store's SQL functions, binding parameters,
# executing a statement, or writing an SQL statement literal outside the
# store is a crossing; callers use the store's own handle, transaction and
# error types. Other services' crates use rusqlite for their own databases,
# so `paths` limits the rule to sbx-mgr's. The patterns are a line-based
# tripwire: aliases, wrapped imports and calls through names imported
# earlier escape them, so they catch common crossings rather than prove
# their absence.
# table) is opened, migrated and queried only by its store, the
# `pplx-space-sbx-mgr-store` crate. The guarantee is that crate's boundary:
# `dependency_fence.sbxmgr_rusqlite` below keeps rusqlite out of every other
# sbx-mgr crate, and outside its `test-support` feature the store's API hands
# out no rusqlite connection, transaction, statement or row. (Its `FromSql`
# impl for a column type can return rusqlite's `FromSqlError`, an error type
# rather than a database capability, to a caller holding a rusqlite value.)
# This ratchet is a line-based tripwire on top of it, within sbx-mgr's
# crates: naming rusqlite, opening a connection or transaction, using the
# shared SQLite open and migration helpers or the shared job store's SQL
# functions, binding parameters, executing a statement, or writing an SQL
# statement literal outside the store is a crossing. Aliases, wrapped
# imports and calls through names imported earlier escape it. Other services' crates use rusqlite for their own databases, so
# `paths` limits the rule to sbx-mgr's.
[rules.pattern_ratchet.sbxmgr_sqlite]
patterns = [
'\brusqlite\s*::',
Expand All @@ -272,10 +275,7 @@ patterns = [
'^\s*(?:SELECT\s|INSERT\s+(?:OR\s+[A-Z]+\s+)?INTO\s|UPDATE\s+(?:OR\s+[A-Z]+\s+)?\w+(?:\s+SET\s|\s*$)|DELETE\s+FROM\s|WITH\s+(?:RECURSIVE\s+)?\w+\s+AS\b)',
]
paths = ["crates/libs/sbx/mgr/**", "crates/apps/sbx/**"]
allow = [
"crates/libs/sbx/mgr/server/src/db.rs",
"crates/libs/sbx/mgr/server/src/db/**",
]
allow = ["crates/libs/sbx/mgr/store/src/**"]

[rules.pattern_ratchet.sbxmgr_sqlite.no_crossing]
mode = "required"
Expand All @@ -294,8 +294,9 @@ mode = "required"
mode = "required"

# The same database's schema and location, in any crate: its migrations, its
# path and file name, and the migrator's default-path helper for it belong to
# the store, which opens and migrates it. The migrations crate defines the
# path and file name, and a default-path helper for it belong to the store,
# which opens and migrates it; the database migrator takes them from the
# store's `db::migration::target()`. The migrations crate defines the
# migrators and common-core the path. These names are
# specific enough to check workspace-wide, unlike `sbxmgr_sqlite`'s patterns,
# which other services' crates match for their own databases.
Expand All @@ -308,18 +309,17 @@ patterns = [
'\bdb/sandbox-manager\b',
]
allow = [
"crates/libs/sbx/mgr/server/src/db.rs",
"crates/libs/sbx/mgr/server/src/db/**",
"crates/libs/sbx/mgr/store/src/**",
"crates/libs/sbx/mgr/migrations/src/**",
"crates/libs/common/core/src/host/linux.rs",
]

[rules.pattern_ratchet.sbxmgr_sqlite_schema.no_crossing]
mode = "required"

# Seeding the ratchet reports its initial entries against the base.
# The baseline is empty: no file outside the store may be added to it.
[rules.pattern_ratchet.sbxmgr_sqlite_schema.no_new_entries]
mode = "advisory"
mode = "required"

[rules.pattern_ratchet.sbxmgr_sqlite_schema.no_raised_caps]
mode = "required"
Expand All @@ -330,6 +330,28 @@ mode = "required"
[rules.pattern_ratchet.sbxmgr_sqlite_schema.stale_entries]
mode = "required"

# Only the store may depend on the SQLite drivers that can open sbx-mgr's
# database, so no other sbx-mgr crate can name rusqlite: no normal, dev or
# build dependency, for any target, under any name.
[rules.dependency_fence.sbxmgr_rusqlite]
packages = ["libsqlite3-sys", "rusqlite"]
members = ["crates/libs/sbx/mgr/**", "crates/apps/sbx/**"]
allow = ["crates/libs/sbx/mgr/store"]

[rules.dependency_fence.sbxmgr_rusqlite.no_crossing]
mode = "required"

# sqlx opens SQLite too, directly or through its core and SQLite driver
# crates. The migrations crate embeds the migrations with it, and the store
# names their `Migrator` type.
[rules.dependency_fence.sbxmgr_sqlx]
packages = ["sqlx", "sqlx-core", "sqlx-sqlite"]
members = ["crates/libs/sbx/mgr/**", "crates/apps/sbx/**"]
allow = ["crates/libs/sbx/mgr/store", "crates/libs/sbx/mgr/migrations"]

[rules.dependency_fence.sbxmgr_sqlx.no_crossing]
mode = "required"

[rules.crate_names]
# A crate matches if a part of its package or library name, lowercased and
# split on `-` and `_`, is one of these.
Expand Down
40 changes: 35 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ members = [
"crates/libs/sbx/mgr/client",
"crates/libs/sbx/mgr/migrations",
"crates/libs/sbx/mgr/server",
"crates/libs/sbx/mgr/store",
"crates/libs/node/api/client",
"crates/libs/node/api/server",
"crates/libs/node/ctl/server",
Expand Down Expand Up @@ -344,6 +345,7 @@ pplx-space-snapshot-store = { path = "crates/libs/snapshot/store" }
pplx-space-sbxmgr-migrations = { path = "crates/libs/sbx/mgr/migrations" }
pplx-space-sbx-mgr = { path = "crates/libs/sbx/mgr/server" }
pplx-space-sbx-mgr-client = { path = "crates/libs/sbx/mgr/client" }
pplx-space-sbx-mgr-store = { path = "crates/libs/sbx/mgr/store" }
pplx-space-spaced-build = { path = "crates/libs/spaced/build" }
pplx-space-spaced-guest-protocol = { path = "crates/libs/spaced/guest/protocol" }
pplx-space-spaced-guest-execution = { path = "crates/libs/spaced/guest/execution" }
Expand Down
15 changes: 7 additions & 8 deletions architecture-baseline.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,6 @@
"crates/libs/object-store/src/lib.rs" = 1810
"crates/libs/observability/src/lib.rs" = 1063
"crates/libs/public/api/src/lib.rs" = 1793
"crates/libs/sbx/mgr/server/src/db/auto_lifecycle_delete_receipts.rs" = 1149
"crates/libs/sbx/mgr/server/src/db/cleanup_episodes.rs" = 1833
"crates/libs/sbx/mgr/server/src/db/quarantine_recovery.rs" = 1042
"crates/libs/sbx/mgr/server/src/db/sandboxes.rs" = 1541
"crates/libs/sbx/mgr/server/src/db/state_transitions.rs" = 1012
"crates/libs/sbx/mgr/server/src/run.rs" = 1091
"crates/libs/sbx/mgr/server/src/sandbox_eviction.rs" = 1253
"crates/libs/sbx/mgr/server/src/service/activation_support.rs" = 1574
Expand All @@ -101,6 +96,11 @@
"crates/libs/sbx/mgr/server/src/snapshot_restore.rs" = 2150
"crates/libs/sbx/mgr/server/src/snapshot_upload_jobs.rs" = 1210
"crates/libs/sbx/mgr/server/src/watchdog.rs" = 2767
"crates/libs/sbx/mgr/store/src/db/auto_lifecycle_delete_receipts.rs" = 1147
"crates/libs/sbx/mgr/store/src/db/cleanup_episodes.rs" = 1830
"crates/libs/sbx/mgr/store/src/db/quarantine_recovery.rs" = 1042
"crates/libs/sbx/mgr/store/src/db/sandboxes.rs" = 1535
"crates/libs/sbx/mgr/store/src/db/state_transitions.rs" = 1012
"crates/libs/spaced/host/client/src/lib.rs" = 1040
"crates/libs/spaced/host/server/src/bridge.rs" = 1249
"crates/libs/template/mgr/src/db.rs" = 1276
Expand Down Expand Up @@ -149,10 +149,9 @@
# transaction and error types, so no file is listed.
[pattern_ratchet.sbxmgr_sqlite]

# Code outside the store that still names sbx-mgr's migrations or database
# path: the database migrator, until it calls the store.
# No code outside the store names sbx-mgr's migrations or database path; the
# database migrator takes them from the store.
[pattern_ratchet.sbxmgr_sqlite_schema]
"crates/libs/db/migrator/src/lib.rs" = 5

# [crate_names] maps each workspace package with a catch-all name (a part such
# as `common`, `utils` or `core`) to its member path. Only remove entries: a pull
Expand Down
6 changes: 6 additions & 0 deletions ci/rust-artifact-inputs.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"crates/libs/common/core",
"crates/libs/common/grpc",
"crates/libs/common/grpc-lb",
"crates/libs/common/jobs",
"crates/libs/common/proto-build",
"crates/libs/common/svc",
"crates/libs/common/work-coalescer",
Expand All @@ -59,6 +60,7 @@
"crates/libs/sandbox/teardown",
"crates/libs/sbx/mgr/client",
"crates/libs/sbx/mgr/migrations",
"crates/libs/sbx/mgr/store",
"crates/libs/spaced/build",
"crates/libs/spaced/common",
"crates/libs/template/mgr-client",
Expand All @@ -81,11 +83,13 @@
"crates/libs/common/core",
"crates/libs/common/grpc",
"crates/libs/common/grpc-lb",
"crates/libs/common/jobs",
"crates/libs/common/proto-build",
"crates/libs/common/svc",
"crates/libs/credential/injection/core",
"crates/libs/credential/mgr/client",
"crates/libs/db/migrator",
"crates/libs/events",
"crates/libs/execution/common",
"crates/libs/metrics",
"crates/libs/net/common",
Expand All @@ -96,6 +100,7 @@
"crates/libs/observability",
"crates/libs/sbx/mgr/client",
"crates/libs/sbx/mgr/migrations",
"crates/libs/sbx/mgr/store",
"crates/libs/spaced/build",
"crates/libs/spaced/common",
"crates/libs/template/mgr-client"
Expand Down Expand Up @@ -258,6 +263,7 @@
"crates/libs/sbx/mgr/client",
"crates/libs/sbx/mgr/migrations",
"crates/libs/sbx/mgr/server",
"crates/libs/sbx/mgr/store",
"crates/libs/snapshot/store",
"crates/libs/spaced/build",
"crates/libs/spaced/common",
Expand Down
48 changes: 48 additions & 0 deletions ci/scripts/run-rust-checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,52 @@ run_fmt_check() {
cargo fmt --all -- --check
}

# sbx-mgr's SQLite store makes its raw connection and statement methods
# public only under its `test-support` feature, which the workspace pass's
# `--all-features` turns on. Lint sbx-mgr's production libraries and
# binaries without dev targets in every feature configuration its images
# are built with, so production code that calls a gated store method fails
# before merge, even behind a feature such as `otel`: no features, the
# release images' set (docker/Dockerfile.rust-build-common) and the Kind
# images' set (docker/Dockerfile.rust-build-kind). The migrator has no
# features of its own.
run_sbxmgr_production_checks() {
local target_dir="$1"
local sbxmgr_feature_sets=(
""
"pplx-space-sbxmgr-svc/otel,pplx-space-sbxmgr-svc/datadog"
"pplx-space-sbxmgr-svc/otel,pplx-space-sbxmgr-svc/datadog,pplx-space-sbxmgr-svc/test-hooks"
)
local sbxmgr_features sbxmgr_feature_args sbxmgr_graph
for sbxmgr_features in "${sbxmgr_feature_sets[@]}"; do
sbxmgr_feature_args=()
if [ -n "${sbxmgr_features}" ]; then
sbxmgr_feature_args=(--features "${sbxmgr_features}")
fi
echo "--- :rust: Running sbx-mgr production clippy without test-support (features: ${sbxmgr_features:-none})"
CARGO_TARGET_DIR="${target_dir}" cargo clippy \
--locked \
-p pplx-space-sbx-mgr-store \
-p pplx-space-sbx-mgr \
-p pplx-space-sbxmgr-svc \
-p pplx-space-db-migrate \
-p pplx-space-db-migrator \
"${sbxmgr_feature_args[@]}" \
--lib --bins \
-- \
-D warnings
sbxmgr_graph="$(cargo tree --locked \
-p pplx-space-sbx-mgr -p pplx-space-sbxmgr-svc \
-p pplx-space-db-migrate -p pplx-space-db-migrator \
"${sbxmgr_feature_args[@]}" \
-e normal,features --prefix none)"
if grep -q '^pplx-space-sbx-mgr-store feature "test-support"' <<<"${sbxmgr_graph}"; then
echo "sbx-mgr's production graph (features: ${sbxmgr_features:-none}) must not enable the store's test-support" >&2
return 1
fi
done
}

run_clippy_checks() {
local target_dir="target/buildkite-lint"

Expand Down Expand Up @@ -276,6 +322,8 @@ run_clippy_checks() {
-- \
-D warnings

run_sbxmgr_production_checks "${target_dir}"

# feature-flags must lint clean with no vendor SDK compiled in; the matching
# dependency-graph assertion lives in run_feature_isolation_checks.
# `--all-targets` so the SDK-free test targets lint too; run_feature_isolation_checks
Expand Down
2 changes: 1 addition & 1 deletion crates/libs/db/migrator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ tracing = { workspace = true }

# internal
pplx-space-common-svc = { workspace = true, features = ["sqlite"] }
pplx-space-sbxmgr-migrations = { workspace = true }
pplx-space-sbx-mgr-store = { workspace = true }

[dev-dependencies]
pplx-space-common-jobs = { workspace = true }
Expand Down
1 change: 0 additions & 1 deletion crates/libs/db/migrator/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ fn main() {
// also invalidate the embedded schema.
watch("../../../../db/postgres");
watch("../../../../db/common");
watch("../../../../db/sandbox-manager");
watch("../../../../db/template-manager");
watch("../../../../db/node-manager");
watch("../../../../db/node-ctl");
Expand Down
Loading
Loading