test(security): add diagnostics contract model foundation#107
Conversation
Model the approved Decision 022-024 CBOR registries, signature domains, digest chains, derivations, evidence state machine, and privacy boundaries against one canonical cross-language fixture. Keep all Go code in _test.go and pin Trigger v1 plus the absence of helper, bridge, and app runtime carriers. The helper binary remains byte-identical to origin/main and no endpoint, credential, namespace, probe, wire, or production behavior is added.
Reproduce the shared CBOR, HMAC, RFC 8032, domain, digest, and derivation fixtures in VaultSyncTests and model parser, state, privacy, and v1 invariants independently in Swift. Keep the fixture resource and every new symbol confined to the test bundle; the app binary contains no M1 capability, domain, or model strings. No app runtime, localization, persistence, wire, or production-call behavior changes.
📝 WalkthroughWalkthroughAdds a cross-language diagnostics-contract test foundation with a shared JSON fixture, strict deterministic CBOR handling, cryptographic golden vectors, capability-query validation, evidence-state modeling, privacy/relay assertions, and fuzz/property-based rejection tests. ChangesDiagnostics contract validation
Estimated code review effort: 4 (Complex) | ~60 minutes Poem
🚥 Pre-merge checks | ✅ 7✅ Passed checks (7 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ios/VaultSyncTests/DiagnosticsContractTests.swift`:
- Around line 39-43: Update the signature assertions in the diagnostics contract
tests, including the checks near the generatedSignature and the corresponding
later test block, to compare each generated signature’s raw bytes directly with
the vector’s golden signature bytes. Retain the existing validity checks if
needed, but ensure byte-for-byte equality is explicitly asserted.
In `@notify/diagnostics_contract_model_test.go`:
- Around line 238-254: Update diagnosticsTestLogSnapshot and
diagnosticsTestPersistenceSnapshot to pass vector.Sentinels through a
representative redaction/encoding path instead of discarding them and returning
fixed literals. Ensure TestDiagnosticsPrivacyAndPersistenceSnapshots verifies
the transformed log and persistence outputs contain no sentinel or other
sensitive diagnostic content, including vault paths, private filenames,
credentials, tokens, keys, or bookmark data; if no encoder exists, explicitly
rename or document these helpers as golden placeholders rather than privacy
guards.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 10e30e14-50c2-4aef-8c4b-87af16bd7e8b
📒 Files selected for processing (7)
ios/VaultSyncTests/DiagnosticsContractTestSupport.swiftios/VaultSyncTests/DiagnosticsContractTests.swiftios/VaultSyncTests/Fixtures/diagnostics-contract-v1.jsonnotify/diagnostics_contract_cbor_test.gonotify/diagnostics_contract_model_test.gonotify/diagnostics_contract_parser_test.gonotify/diagnostics_contract_vectors_test.go
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
**
⚙️ CodeRabbit configuration file
**:![]()
VaultSync
Self-hosted Obsidian vault sync for iPhone and iPad.
Your notes sync peer-to-peer over Syncthing, straight into Obsidian's iOS sandbox — no note cloud, no account, no tracking.![]()
![]()
![]()
🔭 Why VaultSync
- Peer-to-peer & private — syncs directly between your own devices over Syncthing. No note cloud, no account, no tracking.
- Lands in Obsidian — files sync into Obsidian's iOS sandbox, where the app already looks for them.
- Pair by QR, resolve conflicts — connect your server in seconds; settle Markdown conflicts with side-by-side diffs.
- Server changes can wake your iPhone — optional Cloud Relay asks iOS to wake the app after the helper observes a server change. T...
Files:
ios/VaultSyncTests/Fixtures/diagnostics-contract-v1.jsonnotify/diagnostics_contract_cbor_test.goios/VaultSyncTests/DiagnosticsContractTestSupport.swiftnotify/diagnostics_contract_model_test.gonotify/diagnostics_contract_parser_test.goios/VaultSyncTests/DiagnosticsContractTests.swiftnotify/diagnostics_contract_vectors_test.go
**/*
⚙️ CodeRabbit configuration file
**/*: VaultSync syncs private Obsidian notes through Syncthing. Treat data loss,
privacy leaks, security regressions, and broken sync behavior as high priority.
Do not nitpick formatting unless it affects maintainability, correctness, or public API clarity.
Flag any accidental logging, telemetry, crash reporting, or network transfer of note contents,
vault paths, filenames with private context, API keys, APNs tokens, relay keys, or security-scoped bookmark data.
Files:
ios/VaultSyncTests/Fixtures/diagnostics-contract-v1.jsonnotify/diagnostics_contract_cbor_test.goios/VaultSyncTests/DiagnosticsContractTestSupport.swiftnotify/diagnostics_contract_model_test.gonotify/diagnostics_contract_parser_test.goios/VaultSyncTests/DiagnosticsContractTests.swiftnotify/diagnostics_contract_vectors_test.go
notify/**/*.{sh,go}
📄 CodeRabbit inference engine (README.md)
The optional notify sidecar must support server-side wake-up requests and must not receive notes, file or folder names, or vault structure.
Files:
notify/diagnostics_contract_cbor_test.gonotify/diagnostics_contract_model_test.gonotify/diagnostics_contract_parser_test.gonotify/diagnostics_contract_vectors_test.go
**/*.{md,sh,go,swift}
📄 CodeRabbit inference engine (README.md)
Keep Relay-side request observation and wake-ups received on the iPhone as separate diagnostics evidence; one must not be treated as proof of the other.
Files:
notify/diagnostics_contract_cbor_test.goios/VaultSyncTests/DiagnosticsContractTestSupport.swiftnotify/diagnostics_contract_model_test.gonotify/diagnostics_contract_parser_test.goios/VaultSyncTests/DiagnosticsContractTests.swiftnotify/diagnostics_contract_vectors_test.go
notify/**/*.go
⚙️ CodeRabbit configuration file
notify/**/*.go: Review goroutine lifecycle, context cancellation, HTTP timeouts, signal handling, debounce behavior,
Syncthing REST API polling, relay API calls, error classification, and API-key handling.
Flag leaked request bodies, note metadata, Syncthing API keys, relay keys, or APNs-related secrets.
Files:
notify/diagnostics_contract_cbor_test.gonotify/diagnostics_contract_model_test.gonotify/diagnostics_contract_parser_test.gonotify/diagnostics_contract_vectors_test.go
**/*.swift
📄 CodeRabbit inference engine (Custom checks)
For Swift background execution changes, pass if work is bounded, cancellation-aware, handles expiration callbacks, and records errors without leaking private vault data. Fail only when background work can continue unbounded, miss cleanup, or violate iOS background execution constraints.
Files:
ios/VaultSyncTests/DiagnosticsContractTestSupport.swiftios/VaultSyncTests/DiagnosticsContractTests.swift
ios/**/*.swift
📄 CodeRabbit inference engine (README.md)
ios/**/*.swift: Develop the iOS/iPadOS app using Swift 6 and SwiftUI, targeting iOS/iPadOS 18 or later.
Use VoiceOver and Dynamic Type throughout the iOS/iPadOS app.
Support localization in English, German, Spanish, and Simplified Chinese.
Files:
ios/VaultSyncTests/DiagnosticsContractTestSupport.swiftios/VaultSyncTests/DiagnosticsContractTests.swift
⚙️ CodeRabbit configuration file
ios/**/*.swift: Focus on Swift 6 strict concurrency, Sendable/MainActor correctness, Task cancellation,
retain cycles, memory pressure, SwiftUI observation state, StoreKit/APNs flows, and iOS background execution limits.
Pay special attention to BGAppRefreshTask and BGContinuedProcessingTask behavior, expiration handling,
bounded work, and cleanup when the app is suspended or terminated.
Files:
ios/VaultSyncTests/DiagnosticsContractTestSupport.swiftios/VaultSyncTests/DiagnosticsContractTests.swift
ios/**/*.{swift,plist}
📄 CodeRabbit inference engine (README.md)
ios/**/*.{swift,plist}: Use BGAppRefreshTask and BGContinuedProcessingTask when available for background processing, while allowing iOS to decide whether and when the app runs.
Implement APNs silent push handling for optional Cloud Relay wake-ups.
Files:
ios/VaultSyncTests/DiagnosticsContractTestSupport.swiftios/VaultSyncTests/DiagnosticsContractTests.swift
🪛 ast-grep (0.44.1)
notify/diagnostics_contract_cbor_test.go
[warning] 140-140: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: uint16(value)
Note: [CWE-190] Integer Overflow or Wraparound.
(integer-overflow-narrowing-conversion-go)
[warning] 142-142: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: uint32(value)
Note: [CWE-190] Integer Overflow or Wraparound.
(integer-overflow-narrowing-conversion-go)
notify/diagnostics_contract_vectors_test.go
[warning] 365-365: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: uint32(len(vector.FolderID))
Note: [CWE-190] Integer Overflow or Wraparound.
(integer-overflow-narrowing-conversion-go)
🪛 SwiftLint (0.65.0)
ios/VaultSyncTests/DiagnosticsContractTestSupport.swift
[Warning] 375-375: Prefer failable String(bytes:encoding:) initializer when converting Data to String
(optional_data_string_conversion)
🔇 Additional comments (8)
ios/VaultSyncTests/DiagnosticsContractTestSupport.swift (1)
1-467: LGTM!ios/VaultSyncTests/Fixtures/diagnostics-contract-v1.json (1)
1-297: LGTM!notify/diagnostics_contract_vectors_test.go (1)
1-501: LGTM!notify/diagnostics_contract_cbor_test.go (1)
1-333: LGTM!ios/VaultSyncTests/DiagnosticsContractTests.swift (1)
1-38: LGTM!Also applies to: 44-124, 128-390
notify/diagnostics_contract_parser_test.go (1)
1-204: LGTM!notify/diagnostics_contract_model_test.go (2)
3-52: LGTM!Also applies to: 54-130, 132-236, 256-281, 283-322, 338-352, 354-380
1-1: 🎯 Functional Correctness
notify/diagnostics_contract_model_test.gomatches thenotify/package.> Likely an incorrect or invalid review comment.
Document the CryptoKit provider-output boundary while keeping byte-exact RFC and cross-language signatures verified against canonical inputs. Route every synthetic privacy sentinel through a test-only allowlist redaction before log and persistence snapshot encoding. No runtime logger, persistence carrier, wire behavior, credential, namespace, or production path changes.


What & why
Adds the M1 tests-only contract and model foundation required before any Decisions 022-024 runtime carrier. One canonical fixture drives independent Go and Swift verification of the deterministic CBOR subset, exact field registries, signature domains, digest chains, RFC 8032 vectors, the normative bootstrap HMAC, derivations, state-machine properties, privacy snapshots, and v1 wire regressions.
This PR does not implement or authorize a listener, endpoint, credential, pairing action, namespace, probe, Syncthing mutation, upload, controlled download, roundtrip, Cloud Relay contract data, helper release, or production access.
Component(s)
Test-only boundary
ios/VaultSyncTests/; XcodeGen places both model files and the fixture only inVaultSyncTests.xctest.notify/*_test.go;go listleaves the runtimeGoFilesset unchanged.origin/main:71a28d60873b190248acf68430d0190e7204d03a496553a334cd18d983a4c012.Contract and model coverage
Testing
cd go && make patch && go test -tags noassets ./bridge -count=1— passedgofmt -l go/bridge— emptycd notify && go test ./... -count=1— passedcd notify && go vet ./...— passedcd notify && go test -race ./... -count=1— passedgofmt -l notify— emptycd notify && go test -run '^$' -fuzz=FuzzDiagnosticsContractCanonicalCBOR -fuzztime=10s— passed, 666,047 executionsios/scripts/design-token-lint.sh— passedios/scripts/strings-key-parity.sh— passed, 758 keysnotify/scripts/tests/install-dry-run-test.sh— passed without privileged or mutating commandscd ios && xcodegen generate— passedcd ios && xcodebuild test -project VaultSync.xcodeproj -scheme VaultSync -destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=latest' -derivedDataPath /tmp/vaultsync-m1-derived CODE_SIGNING_ALLOWED=NO -quiet— passed3aa520656951085e7fee939663ffba55e9720238No signing, archive, production service, StoreKit, APNs, Trigger, status, probe, Relay, deployment, or release operation was performed.
Impact, compatibility, privacy, and rollback
Release gate
VaultSync 2.0 remains NO-GO. The strongest implemented proof remains a fresh successful local file
ItemFinishedapply after cursor, RFC3339-nanosecond time, and stable engine-generation baselines. Upload is not implemented or confirmed. Controlled download is not implemented or confirmed. Roundtrip is not implemented or confirmed. Authenticated correlation is not implemented. Helper-first rollout and rollback remain unproven and mandatory before later runtime work.Owner approval is required before merge.