xworkmate-app/docs/security/secure-development-rules.md
2026-04-12 22:09:20 +08:00

4.1 KiB

Secure Development Rules

This project ships a Flutter desktop/mobile client that connects to an OpenClaw gateway and handles user-provided credentials, native entitlements, and file attachments. Treat auth, secret handling, storage, transport, and packaging as security-sensitive by default.

1. Configuration And Secrets

  • .env is a bootstrap helper for local development and test only.
  • .env values may prefill the Gateway form, but they must not silently become the persisted runtime configuration.
  • .env values must never trigger an automatic gateway connection.
  • Do not hardcode real hosts, tokens, passwords, or API keys into Dart, native code, Xcode project files, tests, or scripts.
  • Persisted secrets belong in FlutterSecureStorage or an equivalent secure store, never in SharedPreferences.
  • Error banners, logs, debug prints, and screenshots must not expose full secret values.

2. Gateway And Network Trust Boundary

  • Keep the gateway endpoint, auth token, password, and TLS choice explicit.
  • The managed bridge / gateway runtime path is remote-only and pinned to the managed bridge origin.
  • BRIDGE_SERVER_URL must not become the runtime source of truth for bridge startup or task dialog sends.
  • Remote connections must not silently downgrade from TLS to non-TLS.
  • Explicit loopback / non-TLS behavior is only allowed in isolated external ACP self-host test flows, not in the managed bridge / gateway main path.
  • A user-initiated connect action may use the current form values directly for the active handshake. Persistence is a separate concern and must not be required for the immediate request.
  • When changing auth behavior, verify both success and rejection paths.

3. Storage, Logging, And UI Handling

  • Separate display state from secret state. UI text fields may hold user input transiently, but persisted secret storage must be explicit.
  • Do not copy secrets into analytics events, audit trails, widget snapshots, or test golden artifacts.
  • Mask secret values anywhere they are shown after save.
  • If a form field is security-sensitive, saving/submitting must use the current controller value even when the user has not pressed return or changed focus.

4. Files, Attachments, And Workspace Access

  • Only send files the user explicitly selected.
  • Do not auto-attach local files based on workspace discovery, current tab, or inferred context.
  • Limit attachment metadata and payload construction to the selected files.
  • If a feature requires filesystem or shell access, document the boundary and keep it least-privilege.

5. Native Permissions And Packaging

  • Any new entitlement in macos/Runner/*.entitlements, ios/Runner/*.entitlements, or Xcode project capabilities must be minimal and feature-justified.
  • Build or packaging scripts must not embed secrets into the app bundle, DMG, or generated metadata.
  • Packaging and install steps must preserve the same runtime security assumptions as debug builds.

6. Required Verification

Run these baseline checks for security-sensitive changes:

flutter analyze
flutter test
rg -n "\\.env|RuntimeBootstrapConfig|saveGatewayToken|saveGatewayPassword|FlutterSecureStorage|SharedPreferences" lib test
rg -n "token|password|secret|api[_-]?key" lib test ios macos scripts --glob '!**/Pods/**' --glob '!**/*.g.dart'

If device-run integration is needed on macOS, run cases serially:

pkill -f '/build/macos/Build/Products/Debug/XWorkmate.app/Contents/MacOS/XWorkmate' || true
flutter test integration_test/desktop_navigation_flow_test.dart -d macos
pkill -f '/build/macos/Build/Products/Debug/XWorkmate.app/Contents/MacOS/XWorkmate' || true
flutter test integration_test/desktop_settings_flow_test.dart -d macos

If a device-run hangs instead of asserting, mark it as manual follow-up and leave a concrete test path.

7. Stop-Ship Conditions

Do not mark the change complete if any of these remain true:

  • a real token or password is committed or shown in logs
  • .env changed from prefill-only into runtime source of truth
  • remote transport silently dropped TLS
  • a new entitlement was added without justification
  • auth or secret handling changed without regression coverage