.DEFAULT_GOAL := check check: fmt-check clippy test test-federation-off check-appcontext check-handler-deps check-handler-repos check-http-adapter-deps check-federation-off-social check-sqlite-is-ap-free check-binaries-are-thin check-dockerfile-manifests @echo "✅ All checks passed" check-appcontext: @if grep -rn "AppContext" crates/application/src --include="*.rs" | grep -q .; then \ echo "❌ AppContext found in application crate:"; \ grep -rn "AppContext" crates/application/src --include="*.rs"; \ exit 1; \ fi @echo "✅ No AppContext in application crate" check-handler-deps: @if grep -rnE "[A-Za-z0-9_]*Deps(\s*\{|::from\()" crates/adapters/http-axum/src --include="*.rs" --exclude-dir=tests --exclude=tests.rs | grep -q .; then \ echo "❌ hand-built deps struct found in http-axum:"; \ grep -rnE "[A-Za-z0-9_]*Deps(\s*\{|::from\()" crates/adapters/http-axum/src --include="*.rs" --exclude-dir=tests --exclude=tests.rs; \ exit 1; \ fi @echo "✅ No hand-built deps structs in http-axum" check-handler-repos: @if grep -rn "app_ctx\.repos" crates/adapters/http-axum/src --include="*.rs" --exclude-dir=tests --exclude=tests.rs | grep -q .; then \ echo "❌ app_ctx.repos referenced in http-axum:"; \ grep -rn "app_ctx\.repos" crates/adapters/http-axum/src --include="*.rs" --exclude-dir=tests --exclude=tests.rs; \ exit 1; \ fi @echo "✅ No app_ctx.repos references in http-axum" HTTP_ADAPTER_ALLOWED_ADAPTERS := check-http-adapter-deps: @deps=$$(awk '/^\[dependencies\]/{f=1;next} /^\[/{f=0} f' crates/adapters/http-axum/Cargo.toml \ | sed -n 's/^\([A-Za-z0-9_-]\{1,\}\)[[:space:]]*=.*/\1/p'); \ bad=""; \ for a in $$(ls crates/adapters); do \ case " $(HTTP_ADAPTER_ALLOWED_ADAPTERS) " in *" $$a "*) continue;; esac; \ if echo "$$deps" | grep -qx "$$a"; then bad="$$bad $$a"; fi; \ done; \ if [ -n "$$bad" ]; then \ echo "❌ http-axum depends on adapter crate(s):$$bad"; \ echo " http-axum may name renderers, not reachers — see ADR-0008."; \ exit 1; \ fi; \ echo "✅ http-axum depends on no other adapter crate" check-federation-off-social: @if grep -n "NoopSocialCommand\|NoopSocialQuery" crates/bootstrap/src/federation.rs | grep -q .; then \ echo "❌ bootstrap wires social noops — federation-off would report an empty follow graph:"; \ grep -n "NoopSocialCommand\|NoopSocialQuery" crates/bootstrap/src/federation.rs; \ exit 1; \ fi @if ! awk '/cfg\(not\(feature = "federation"\)\)/ && !started {started=1} started && /cfg\(feature = "federation"\)/ {exit} started {print}' crates/bootstrap/src/federation.rs | grep -q "LocalSocialService"; then \ echo "❌ LocalSocialService not wired in the federation-off region of crates/bootstrap/src/federation.rs — federation-off has no social behavior wired at all, not even noops"; \ exit 1; \ fi @echo "✅ bootstrap wires real social behavior in every configuration" BINARIES_ALLOWED_DEPS := bootstrap config tokio axum anyhow dotenvy tracing check-binaries-are-thin: @bad=""; \ for c in server worker; do \ deps=$$(awk '/^\[dependencies\]/{f=1;next} /^\[/{f=0} f' crates/$$c/Cargo.toml \ | sed -n 's/^\([A-Za-z0-9_-]\{1,\}\)[[:space:]]*=.*/\1/p'); \ for d in $$deps; do \ case " $(BINARIES_ALLOWED_DEPS) " in *" $$d "*) continue;; esac; \ bad="$$bad $$c:$$d"; \ done; \ done; \ if [ -n "$$bad" ]; then \ echo "❌ binary [dependencies] outside {$(BINARIES_ALLOWED_DEPS)}:$$bad"; \ echo " wiring belongs in crates/bootstrap — see ADR-0013."; \ exit 1; \ fi; \ echo "✅ server and worker depend only on {$(BINARIES_ALLOWED_DEPS)}" check-sqlite-is-ap-free: @if grep -nE '^[[:space:]]*(k-ap|activitypub[A-Za-z0-9_-]*|[A-Za-z0-9_-]+-federation)[[:space:]]*=' crates/adapters/sqlite/Cargo.toml | grep -q .; then \ echo "❌ sqlite crate depends on ActivityPub:"; \ grep -nE '^[[:space:]]*(k-ap|activitypub[A-Za-z0-9_-]*|[A-Za-z0-9_-]+-federation)[[:space:]]*=' crates/adapters/sqlite/Cargo.toml; \ exit 1; \ fi @echo "✅ sqlite crate depends on no k-ap, activitypub, or *-federation crate" check-dockerfile-manifests: @members=$$(awk '/^members = \[/{f=1;next} f&&/^\]/{f=0} f' Cargo.toml | sed -n 's/^[[:space:]]*"\(.*\)",\{0,1\}[[:space:]]*$$/\1/p'); \ copied=$$(sed -n 's/^COPY \([^[:space:]]*\)\/Cargo\.toml[[:space:]].*/\1/p' Dockerfile | grep -v '^\(Cargo\.toml\|\.\)$$' || true); \ bad=""; \ for m in $$members; do \ echo "$$copied" | grep -qx "$$m" || bad="$$bad missing-COPY:$$m"; \ done; \ for c in $$copied; do \ echo "$$members" | grep -qx "$$c" || bad="$$bad not-a-member:$$c"; \ done; \ if [ -n "$$bad" ]; then \ echo "❌ Dockerfile manifest COPY lines out of sync with workspace members:$$bad"; \ exit 1; \ fi; \ echo "✅ Dockerfile copies a manifest for every workspace member" fmt: cargo fmt fmt-check: cargo fmt --check clippy: cargo clippy --workspace --all-targets -- -D warnings test: cargo test --workspace test-federation-off: cargo test --workspace --no-default-features fix: cargo fmt cargo clippy --fix --allow-dirty --allow-staged # Run the dev stack: # server (:3000, in the foreground, Ctrl-C stops it) # worker (background, log at /tmp/movies-diary-worker.log) # spa (:5173, background, log at /tmp/movies-diary-spa.log) # Tear down the background processes with `make dev-stop`. # .env enables EVENT_BUS_BACKEND=nats, so both binaries are built with the nats feature. dev: dev-worker dev-spa cargo run -p server --features nats dev-stop: -pkill -f '[t]arget.debug.worker' || true -pkill -f '[s]pa/node_modules/[.]bin/vite' || true @echo "dev stack stopped" dev-worker: @bash -c 'nohup cargo run -p worker --features nats >> /tmp/movies-diary-worker.log 2>&1 & echo "worker → pid $$! (log: /tmp/movies-diary-worker.log)"' dev-spa: @bash -c 'nohup npm --prefix spa run dev >> /tmp/movies-diary-spa.log 2>&1 & echo "spa → pid $$! (log: /tmp/movies-diary-spa.log, http://localhost:5173)"' spa-dev: @npm --prefix spa run dev .PHONY: check fmt fmt-check clippy test test-federation-off fix dev dev-stop dev-worker dev-spa spa-dev check-appcontext check-handler-deps check-handler-repos check-http-adapter-deps check-federation-off-social check-sqlite-is-ap-free check-binaries-are-thin check-dockerfile-manifests