Skip to content

Protect DSV completion proof while handling notifications - #65

Draft
OziinG wants to merge 25 commits into
devfrom
cc-312-completion-notification-integration
Draft

OziinG wants to merge 25 commits into
devfrom
cc-312-completion-notification-integration

Conversation

@OziinG

@OziinG OziinG commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

DSV Driver의 배송 완료·사진 증빙을 알림 이동 보호에 연결합니다. 완료 확인, 사진 선택, 미리보기와 업로드 중 알림을 눌러도 입력과 사진을 유지합니다. 작업 종료 뒤 서버에서 목적지를 다시 확인합니다. 확정 거절은 수정·닫기를 허용합니다. 결과가 불명확하면 원래 identity와 시각을 유지합니다. 결과 복구 후 자동 후속 작업을 중단하고 “닫고 배정 확인”으로 현재 배정을 조회합니다. 실기기에서 재현한 복구 버튼 잘림도 수정했습니다.

원본 PR61 a7959e5a와 PR64 6e2db49e를 새 격리 branch에서 결합했습니다. 원본 PR·worktree, 업무용 앱·데이터와 서명 자료를 보존했습니다. 합성 기능은 정확한 suffix package, 두 flag와 loopback HTTP를 모두 확인합니다. 일반 package의 환경 오염 부정 검사도 통과했습니다.

  • 최종 HEAD: 047d57fdb783294ba4a48e62715387842cd8f65c.
  • 실행·APK 소스: f5609529a00d9a39ea12ad81319183e5de5bac20. 이후 commit은 검증 문서만 변경합니다.
  • 서버: Draft PR487 18ea784934ec3cf511f56646b708d141617c404b. PR483 44e6d880 위의 최소 계약입니다. owner migration을 먼저 적용해야 합니다.
  • 웹 연결 기준: PR85 72709e3.

Galaxy Note20/Android13, 실제 API, 독립 PostgreSQL17의 114 migrations와 격리 proof storage로 최종 검증했습니다. N06 정확한 대상, 실제 연결403 후 편집·닫기, 네 단계의 개별 알림 탭과 사진 유지가 PASS입니다. 최초202 후 사진503·실제201 응답 유실·같은 key 재시도에서도 완료 event, 승인 시각과 증빙은 각각1개로 유지됐습니다. 사진 재시도는 완료 POST를 반복하지 않습니다. 불명확한 완료의 직접 duplicate200 복구와 재배정 후 ACTIVE 계정 APPLIED 복구도 PASS입니다. 안전 닫기 전 자동 사진·경로 POST가 없으며 닫기 뒤 현재 배정을 확인합니다. 독립 실기기 검토는 APPROVE입니다.

Driver 전체401/401, typecheck, lint, Expo alignment와 whitespace는 PASS입니다. 실행 소스 CI37649139688는 workspace·lint·Android/iOS export PASS, npm audit high20/critical0으로 FAILURE입니다. 이후 alignment·whitespace는 skipped이며 같은 로컬 검사는 PASS입니다. Issue62 audit 기준과 출시 차단을 유지합니다.

APK: com.evnsolution.clever.driver.integration, 0.1.15(26), Android Debug / APKv2 / RSA2048. SHA256 c40780e63c0ce24c823091b1950d3e0222c3315dffdc4274e73fe15f2d49274d. 설치 직후와 검증 후 base.apk 해시가 같습니다. 검증 문서에 화면·HTTP·DB·업로드 파일의 연결과 제한을 기록했습니다. 114파일의 최종 private manifest와 독립 검토를 보존했습니다. 소유 격리 서비스, adb reverse와 기기 합성 원본 사진만 정리했습니다. PG 데이터·업로드 증빙·suffix 앱 상태는 보존했습니다.

카메라 권한 거부·허용과 native camera 실행은 확인했습니다. 최종 증빙은 Android Photo Picker의 합성 사진입니다. 카메라 촬영본 업로드는 미검증입니다. 새 전체 사진 오프라인 큐는 없습니다. 실제 FCM, 실차 GPS, 운영 정책, 운영 DB, AWS, 병합, 배포, 스토어 게시와 P7은 제외합니다. 원시 자료와 비밀은 코드 PR에 올리지 않습니다.

Refs #63
Change-control: EVNSolution/clever-change-control#312

Combine the completion time, optional POD photo, and final confirmation in one flow while preserving the existing server event and media contracts.

Constraint: The selected time is actual completion evidence and must stay separate from Rolling ETA.
Rejected: Separate completion and proof dialogs | They split one delivery decision across two confirmations.
Confidence: high
Scope-risk: moderate
Directive: Keep completion time and predicted arrival labels distinct in future UI changes.
Tested: npm run check:workspace; git diff --check
Not-tested: Physical camera and gallery selection; production proof upload.
Keep reset credential entry on the DSV HTTPS page while exposing login help and invalidated-session cleanup in the app.

Constraint: Approved server contract uses administrator-issued 30-minute one-time HTTPS links and no SMS OTP or app reset endpoint
Rejected: Add app reset API or deep-link handling | no approved contract
Confidence: high
Scope-risk: narrow
Directive: Keep reset token handling on DSV web unless the server contract changes
Tested: npm run check:workspace; npm run lint; npx expo install --check; npm run build; git diff --check
Not-tested: physical-device interaction
Present the persisted last stop arrival and server pickup-to-arrival duration on the Driver delivery screen while preserving the existing next-stop ETA and completion flow.

Constraint: The deployed DSV contract owns stop ETA, pickup time, route sequence, and timezone
Rejected: Calculate ETA from device time, distance, or final service time | those inputs are not an approved completion ETA contract
Confidence: high
Scope-risk: narrow
Directive: Keep this value labeled as final-stop arrival until the server exposes a completion ETA
Tested: npm run check:workspace; npm run lint; npx expo install --check; npm run build; git diff --check
Not-tested: physical device or emulator UI because none was connected or booted
Advance the public version beyond the deployed Play build and keep Android and iOS build identifiers explicit for local validation.

Constraint: Google Play already serves versionCode 25 and App Store Connect already received build 14.
Rejected: Reusing 0.1.14 or a versionCode below 26 | Store uploads require monotonically increasing identifiers.
Confidence: high
Scope-risk: narrow
Directive: Do not lower versionCode or buildNumber when regenerating native projects.
Tested: npm run check:workspace; npm run lint; npx expo install --check; git diff --check
Not-tested: Signed store builds and device installation.
Enable durable R8 minification, optimized defaults, and resource shrinking through the Expo prebuild boundary.

Constraint: The Android directory is generated and must remain reproducible from app configuration.

Rejected: Edit generated Gradle files directly | Expo prebuild would discard the optimization settings.

Confidence: high

Scope-risk: narrow

Directive: Preserve the template guard when upgrading Expo and review any generated ProGuard default change explicitly.

Tested: Clean Expo prebuild proof; workspace typecheck and 170 tests; lint; Expo dependency check; git diff check.

Not-tested: Signed production AAB awaits the EAS remote build because local native compilation exceeded the 8 GB host budget.
Constraint: Local release validation must protect an 8 GB host and stay distinct from Play candidates.
Rejected: Hardcode generated .cxx paths and targets | They change across generated native builds.
Confidence: high
Scope-risk: narrow
Directive: Stop native builds at the documented fan-out and memory-pressure boundaries before retrying.
Tested: npm run check:workspace; npm run lint; npx expo install --check; git diff --check
Not-tested: Production Play AAB remains blocked by the exhausted EAS Android quota.
Lock and display the accepted completion time during proof retries. Align Expo SDK 56 patch dependencies and update the existing brace-expansion override without changing audit gates.

Refs #1 and EVNSolution/clever-change-control#240.

Constraint: Delivery completion and proof upload use separate server operations.
Rejected: Resubmit completion after proof failure | It duplicates accepted delivery events.
Confidence: high
Scope-risk: moderate
Directive: Preserve the accepted completion time during retries and keep audit failures visible.
Tested: Node 20.19.4; typecheck; 174 tests; lint; Expo alignment; Android export with one Metro worker; git diff --check.
Known-failure: npm audit reports 20 high findings from unpatched braces and node-forge advisories; no audit exemption or SDK downgrade applied.
Not-tested: Physical-device camera and proof roundtrip; signed native/store artifacts; iOS export.
Unresolved notification clicks and small user commands survive recovery without
converting reads into business events or applying stale work to another assignment.

Constraint: PR483 is unmerged and undeployed; D05 and Issue62 remain gates.
Rejected: Legacy start fallback after unknown atomic result | can duplicate partial business events.
Confidence: high
Scope-risk: moderate
Directive: Keep new APIs OFF until server, policy, security and device gates are cleared.
Tested: Typecheck, 253 tests, lint, Expo alignment, Android Hermes export, diff check and independent review.
Not-tested: Real FCM, native candidate installation, production server integration and iOS.
Separate inbox receipts from business reads and defer navigation until the user
finishes protected work. Recheck authority before moving and consume clicks only
after a fresh visible destination commit. Reject malformed operational identities.

Constraint: Driver PR64 management review R1-R3; dev remains the integration base
Rejected: Discarding drafts or consuming unresolved clicks | interrupts driver work and hides unresolved authority
Confidence: high
Scope-risk: moderate
Directive: Preserve the pending lease during editing, dialogs, saving and proof; never bypass Issue62
Tested: TypeScript; 319 tests; lint; Expo alignment; whitespace; independent review 66 tests
Not-tested: New native APK; real FCM; new candidate device screens; server runtime integration
Constraint: Native integration checks must not replace the business package, Firebase configuration, or production API endpoint.
Rejected: Install the PR candidate with the production application ID | This could overwrite the business install and reuse real provider configuration.
Confidence: high
Scope-risk: narrow
Directive: Use build:android:integration:apk only with an isolated local server; FCM delivery remains a separate unverified gate.
Tested: Targeted project convention tests and Expo config resolution for production and isolated modes.
Not-tested: Native APK build and device installation are pending the coordinated heavy-build window.
The Expo android config field did not reach the release manifest. Apply cleartext access through an isolated-only config plugin while production keeps its existing Firebase and network configuration.

Constraint: Only the suffix integration package may use loopback HTTP.

Rejected: android.usesCleartextTraffic app config field | Expo omitted it from the generated release manifest.

Confidence: high

Scope-risk: narrow

Directive: Keep this plugin behind CLEVER_DRIVER_ISOLATED_ANDROID and never enable cleartext in the business package.

Tested: project convention 4/4; isolated Expo prebuild; release manifest inspection; arm64 APK build and device login.

Not-tested: Real FCM delivery because the isolated build intentionally has no Firebase provider config.
Capture the fresh audit blocker, actual PostgreSQL client replay proof, native APK provenance, suffix installation, device login recovery, and remaining provider limits.

Constraint: Keep export, debug APK, installed device evidence, and real FCM evidence distinct.

Rejected: Treating runtime bundle absence as an audit waiver | Issue62 remains blocked by unpatched upstream advisories.

Confidence: high

Scope-risk: narrow

Directive: Do not describe this isolated result as production activation or release-signing evidence.

Tested: CI 37570524933; actual PostgreSQL client flow; APK manifest/signature/ABI; suffix install; synthetic device login and relaunch recovery.

Not-tested: Real FCM, release signing, native camera and permission flow, production GPS, deployment.
Apply the cleartext policy in both modes and use a guarded prebuild helper. The helper cleans only managed mode transitions or Firebase residue, preserves same-mode caches, and verifies package, manifest, and Firebase output before recording the mode.

Constraint: Preserve business Firebase and signing material while keeping operational features and custom API overrides off in release builds.

Rejected: Unconditional clean prebuild | It discards valid same-mode native generation and conflicts with the persistent release workspace.

Confidence: high

Scope-risk: narrow

Directive: Use the mode-aware helper for Android APK generation; do not bypass its generated-output checks.

Tested: Actual isolated-to-production nonclean prebuild; mode transition and residue guards; targeted policy tests 12/12; workspace tests 325/325, typecheck, lint, Expo alignment; diff check.

Not-tested: Business Firebase credentials, release signing, Play submission, or production deployment.
The isolated APK needs an OS notification tap that exercises the production response classifier and resolver. The scheduler accepts only authenticated inbox identities under the integration package and loopback verification guard.

Constraint: Keep FCM registration and foreground push receipts restricted to the production package.
Rejected: Add a deep link or Android broadcast backdoor | It would bypass the production notification response path.
Confidence: high
Scope-risk: narrow
Directive: Count this path as synthetic local notification evidence, never as actual FCM receipt evidence.
Tested: Targeted notification tests 17/17, targeted ESLint, full workspace checks by root, and git diff --check passed.
Not-tested: Final rebuilt APK installation and physical notification shade tap are owned by the device verification lane.
Constraint: D05 operational reasons remain unapproved and default empty
Rejected: Enable synthetic reasons for normal installs | would treat a fixture as operational policy
Confidence: high
Scope-risk: narrow
Directive: Keep the explicit verification flag and loopback API fence together
Tested: Driver typecheck, 325 tests, lint, Expo alignment, isolated APK build
Not-tested: Real FCM, live GPS, operational policies, production signing
Render the deferred-notification banner as a bottom SafeArea overlay and place both decisions in visible 44-point action buttons. This keeps the active workspace mounted while making the required actions reachable on tall Android devices.

Constraint: Preserve the pending notification, active input, and navigation acknowledgement rules.

Rejected: A normal-flow banner below the workspace | The Note20 layout clipped both actions outside the authenticated safe area.

Confidence: high

Scope-risk: narrow

Directive: Keep deferred-notification actions inside a bottom SafeArea container and retain minimum touch height.

Tested: driverNotificationWorkProtection 52/52; rendered alert safe-area edges, absolute bounds, and both 44-point actions; diff check; independent re-review APPROVE.

Not-tested: Rebuilt APK and final Note20 tap evidence; root runs these sequentially.
Constraint: Preserve PR61, business app data and the Issue62 audit gate.
Confidence: high
Scope-risk: narrow
Directive: Synthetic Android notification taps do not prove FCM or production activation.
Tested: Actual Note20 UI flows with PostgreSQL/API correlation; fixed protected actions; 325 tests; typecheck; lint; native APK and installed hash.
Not-tested: Real FCM, live vehicle GPS, production signing, camera/POD and unapproved operational policies.
…vigation

Constraint: Combine Driver PR61 and PR64 without modifying either source branch
Rejected: Navigate immediately from proof modal | Loses active completion input and selected media
Confidence: high
Scope-risk: moderate
Directive: Keep Issue62 audit gate and isolated package flags; do not add a full photo offline queue
Tested: 99 integration regressions; package contamination guard; native generation isolation
Not-tested: Real FCM, vehicle GPS, production policies, release signing and P7
Constraint: Completion and proof uploads use the existing server idempotency contracts.
Rejected: Generating a new command ID for each retry | A lost accepted response creates duplicate completion and proof records.
Confidence: high
Scope-risk: narrow
Directive: Preserve completion identity and selected-photo key until their transaction ends; do not add a full offline photo queue.
Tested: Typecheck and 360 workspace tests; 99 connected protection regressions; 9 API tests; lint; Expo alignment; whitespace.
Not-tested: Physical-device acceptance of this source and production FCM, vehicle GPS, signing, deployment, and P7.
Constraint: Original PR61 and PR64, business app data, and signing material must remain unchanged.
Confidence: high
Scope-risk: narrow
Directive: Retain Issue62 audit gate and distinguish APK source from documentation-only commits.
Tested: Physical Android acceptance; one completion event, one proof record/file, four fresh destination resolves; independent review; 360 app tests and 65 PostgreSQL HTTP tests.
Not-tested: Camera-captured photo upload, real FCM, vehicle GPS, production systems, release signing, and P7.
Confidence: high
Scope-risk: narrow
Directive: Preserve the unchanged APK source and the Issue62 audit block.
Tested: Documentation against completed cleanup records and CI 37600176843; executable diff unchanged.
Not-tested: No new native build for this documentation-only update.
Constraint: A destination command can commit stops separately and lose its response.
Rejected: Unlocking every HTTP 4xx | A previous attempt can already be committed.
Confidence: high
Scope-risk: moderate
Directive: Trust only explicit no-apply results before the first unknown outcome; recover through the original account result contract.
Tested: Driver workspace 398/398, lint, Expo alignment, and diff checks.
Not-tested: This source APK and isolated runtime acceptance are pending.
Constraint: Even an exact duplicate approval can follow assignment changes.
Rejected: Automatically uploading proof after an unknown command succeeds | Captured route finalization can be stale.
Confidence: high
Scope-risk: narrow
Directive: Preserve the original time and photo until explicit close, then reload current assignment before further work.
Tested: Driver workspace 401/401, lint, Expo alignment, focused unknown-result and photo-only retry regressions, diff check.
Not-tested: Exact APK device acceptance is pending.
OziinG added 2 commits October 8, 2026 01:03
Constraint: Recovery must preserve the selected photo and approved completion time
Rejected: Hide the photo to expose the close action | Evidence must remain reviewable
Confidence: high
Scope-risk: narrow
Directive: Keep protected-work actions outside the scrollable proof body
Tested: TypeScript; 401 tests; lint; Expo alignment; whitespace
Not-tested: Updated APK device acceptance follows this commit
Constraint: The executable APK source and later documentation HEAD must remain distinct
Confidence: high
Scope-risk: narrow
Directive: Preserve the private raw evidence, original PRs, and Issue62 audit block
Tested: Final f560952 device flows, linked HTTP/DB/proof records, independent APPROVE, documentation accuracy, owned cleanup, whitespace
Not-tested: Real FCM, vehicle GPS, captured-camera upload, production policy, deployment, and P7
@OziinG OziinG changed the title Preserve delivery completion and photo evidence during notification navigation Protect DSV completion proof while handling notifications Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant