From 5f7b9a7360d8dbef5e18b50a76f90f430fe41ef5 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 30 Jun 2026 15:16:14 +0900 Subject: [PATCH] Initial Baron Safe app scaffold --- .gitea/workflows/ci.yaml | 17 ++++++++++++++++ .gitignore | 37 +++++++++++++++++++++++++++++++++++ .vscode/extensions.json | 8 ++++++++ .vscode/settings.json | 5 +++++ .vscode/tasks.json | 23 ++++++++++++++++++++++ README.md | 31 +++++++++++++++++++++++++++++ app/android/.gitkeep | 0 app/integration_test/.gitkeep | 0 app/ios/.gitkeep | 0 app/lib/main.dart | 33 +++++++++++++++++++++++++++++++ app/pubspec.yaml | 28 ++++++++++++++++++++++++++ app/test/.gitkeep | 0 docker-compose.yaml | 15 ++++++++++++++ docker/Dockerfile.flutter-ci | 3 +++ docker/Dockerfile.web | 2 ++ docker/nginx.conf | 11 +++++++++++ docs/api-contract.md | 19 ++++++++++++++++++ docs/architecture.md | 19 ++++++++++++++++++ docs/bridge-policy.md | 19 ++++++++++++++++++ docs/release-policy.md | 23 ++++++++++++++++++++++ scripts/bootstrap.sh | 4 ++++ scripts/build-android.sh | 4 ++++ scripts/build-ios.sh | 4 ++++ scripts/test.sh | 5 +++++ 24 files changed, 310 insertions(+) create mode 100644 .gitea/workflows/ci.yaml create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 README.md create mode 100644 app/android/.gitkeep create mode 100644 app/integration_test/.gitkeep create mode 100644 app/ios/.gitkeep create mode 100644 app/lib/main.dart create mode 100644 app/pubspec.yaml create mode 100644 app/test/.gitkeep create mode 100644 docker-compose.yaml create mode 100644 docker/Dockerfile.flutter-ci create mode 100644 docker/Dockerfile.web create mode 100644 docker/nginx.conf create mode 100644 docs/api-contract.md create mode 100644 docs/architecture.md create mode 100644 docs/bridge-policy.md create mode 100644 docs/release-policy.md create mode 100755 scripts/bootstrap.sh create mode 100755 scripts/build-android.sh create mode 100755 scripts/build-ios.sh create mode 100755 scripts/test.sh diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml new file mode 100644 index 0000000..8cb3693 --- /dev/null +++ b/.gitea/workflows/ci.yaml @@ -0,0 +1,17 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + flutter-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Show scaffold + run: find . -maxdepth 3 -type f | sort + - name: Flutter placeholder + run: echo "Configure Flutter runner before enabling analyze/test in Gitea Actions." diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3862318 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Flutter/Dart +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +build/ +coverage/ + +# Android/iOS generated/local files +app/android/.gradle/ +app/android/local.properties +app/ios/Pods/ +app/ios/.symlinks/ +app/ios/Flutter/ephemeral/ +app/ios/Flutter/Generated.xcconfig +app/ios/Flutter/flutter_export_environment.sh + +# IDE +.idea/ +*.iml +.vscode/*.log + +# Env/secrets +.env +.env.* +*.keystore +*.jks +*.p8 +*.mobileprovision +*.cer +*.pem + +# OS +.DS_Store +Thumbs.db diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..8be98b7 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "Dart-Code.dart-code", + "Dart-Code.flutter", + "ms-azuretools.vscode-docker", + "humao.rest-client" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..31b5d95 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "dart.flutterSdkPath": null, + "editor.formatOnSave": true, + "files.eol": "\n" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..b9a6f1f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "flutter analyze", + "type": "shell", + "command": "cd app && flutter analyze", + "problemMatcher": [] + }, + { + "label": "flutter test", + "type": "shell", + "command": "cd app && flutter test", + "problemMatcher": [] + }, + { + "label": "docker compose up", + "type": "shell", + "command": "docker compose up baron-safe-web", + "problemMatcher": [] + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..16b0c09 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# Baron Safe App + +Baron Safe is a PWA/WebView hybrid mobile app for Baron SSO login confirmation, session review, and suspicious session blocking. + +## Development Direction + +- Keep the existing `userfront` repository unchanged. +- Reuse applicable `userfront` UI flow, Flutter patterns, routing, and API interaction style. +- Use WebView for information display and user interaction. +- Delegate push, biometric authentication, secure storage, and future device signing to native or Flutter plugin layers. + +## Initial Flow + +1. User enters a phone number in Baron SSO or an RP login screen. +2. Baron SSO proceeds with the existing login policy. +3. Login/session history is recorded. +4. Baron Safe receives a login notification via FCM/APNs. +5. User checks service, IP, device, time, and auth method in Baron Safe. +6. If suspicious, the user blocks the session or linked RP. + +## Repository Layout + +```text +baron-safe-app/ + docs/ + app/ + docker/ + scripts/ + .vscode/ + .gitea/workflows/ +``` diff --git a/app/android/.gitkeep b/app/android/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/integration_test/.gitkeep b/app/integration_test/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/ios/.gitkeep b/app/ios/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/lib/main.dart b/app/lib/main.dart new file mode 100644 index 0000000..bca82c9 --- /dev/null +++ b/app/lib/main.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +void main() { + runApp(const ProviderScope(child: BaronSafeApp())); +} + +class BaronSafeApp extends StatelessWidget { + const BaronSafeApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Baron Safe', + theme: ThemeData(useMaterial3: true), + home: const BaronSafeHome(), + ); + } +} + +class BaronSafeHome extends StatelessWidget { + const BaronSafeHome({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Baron Safe')), + body: const Center( + child: Text('Baron Safe hybrid app scaffold'), + ), + ); + } +} diff --git a/app/pubspec.yaml b/app/pubspec.yaml new file mode 100644 index 0000000..f165a32 --- /dev/null +++ b/app/pubspec.yaml @@ -0,0 +1,28 @@ +name: baron_safe_app +description: Baron Safe hybrid mobile app for Baron SSO. +publish_to: "none" +version: 0.1.0+1 + +environment: + sdk: ">=3.4.0 <4.0.0" + +dependencies: + flutter: + sdk: flutter + flutter_riverpod: ^3.0.3 + go_router: ^17.0.1 + http: ^1.6.0 + webview_flutter: ^4.10.0 + local_auth: ^2.3.0 + flutter_secure_storage: ^9.2.2 + firebase_core: ^3.8.0 + firebase_messaging: ^15.1.5 + logging: ^1.2.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^4.0.0 + +flutter: + uses-material-design: true diff --git a/app/test/.gitkeep b/app/test/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..4810c17 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,15 @@ +services: + baron-safe-web: + image: nginx:1.27-alpine + ports: + - "18080:80" + volumes: + - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro + - ./app/build/web:/usr/share/nginx/html:ro + + flutter-ci: + build: + context: ./docker + dockerfile: Dockerfile.flutter-ci + volumes: + - ./app:/workspace/app diff --git a/docker/Dockerfile.flutter-ci b/docker/Dockerfile.flutter-ci new file mode 100644 index 0000000..fe2d1da --- /dev/null +++ b/docker/Dockerfile.flutter-ci @@ -0,0 +1,3 @@ +FROM ghcr.io/cirruslabs/flutter:stable +WORKDIR /workspace/app +CMD ["flutter", "--version"] diff --git a/docker/Dockerfile.web b/docker/Dockerfile.web new file mode 100644 index 0000000..06132e3 --- /dev/null +++ b/docker/Dockerfile.web @@ -0,0 +1,2 @@ +FROM nginx:1.27-alpine +COPY nginx.conf /etc/nginx/conf.d/default.conf diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..69e7291 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,11 @@ +server { + listen 8080; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/docs/api-contract.md b/docs/api-contract.md new file mode 100644 index 0000000..b78941e --- /dev/null +++ b/docs/api-contract.md @@ -0,0 +1,19 @@ +# API Contract Draft + +## Initial APIs + +- `POST /api/v1/baron-safe/devices/register` +- `POST /api/v1/baron-safe/devices/push-token` +- `DELETE /api/v1/baron-safe/devices/{deviceId}` +- `GET /api/v1/baron-safe/sessions` +- `GET /api/v1/baron-safe/sessions/{sessionId}` +- `POST /api/v1/baron-safe/sessions/{sessionId}/block` +- `GET /api/v1/baron-safe/linked-apps` +- `POST /api/v1/baron-safe/linked-apps/{clientId}/block` + +## Future High-Risk Approval APIs + +- `POST /api/v1/auth/baron-safe/login/init` +- `GET /api/v1/auth/baron-safe/requests/{authReqId}` +- `POST /api/v1/auth/baron-safe/requests/{authReqId}/decision` +- `POST /api/v1/auth/baron-safe/login/poll` diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..95cd742 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,19 @@ +# Architecture + +## Principle + +Baron Safe is developed as a hybrid app. The WebView layer presents session, linked app, QR, and portal-style screens. Native or Flutter plugin layers handle sensitive capabilities. + +## Layers + +| Layer | Responsibility | +| --- | --- | +| WebView | Display session history, linked apps, details, and user actions | +| Native/Plugin | Push, biometric prompt, secure storage, future key signing | +| Backend | Device registration, push trigger, session query, session blocking, audit logs | + +## Default UX + +The initial model is post-login confirmation and blocking: + +`phone number login -> login allowed -> Baron Safe notification -> user confirmation -> block if suspicious` diff --git a/docs/bridge-policy.md b/docs/bridge-policy.md new file mode 100644 index 0000000..e914a59 --- /dev/null +++ b/docs/bridge-policy.md @@ -0,0 +1,19 @@ +# WebView-Native Bridge Policy + +## Allowed Commands + +| Command | Description | +| --- | --- | +| `getDeviceInfo` | Return device id, platform, app version | +| `registerPushToken` | Register current push token | +| `openBiometricPrompt` | Run biometric or device PIN prompt | +| `blockSession` | Block a session after native verification | +| `blockLinkedApp` | Block a linked RP after native verification | +| `openSettings` | Open native app settings | + +## Rules + +- Do not pass private keys to WebView. +- Do not store long-lived refresh tokens in WebView storage. +- Validate origin and session before processing bridge commands. +- Native layer must verify sensitive commands before calling backend APIs. diff --git a/docs/release-policy.md b/docs/release-policy.md new file mode 100644 index 0000000..04abf23 --- /dev/null +++ b/docs/release-policy.md @@ -0,0 +1,23 @@ +# Release Policy Draft + +## Channels + +| Channel | Purpose | +| --- | --- | +| local | Developer verification | +| staging | Internal QA and SSO integration testing | +| production | Internal/partner release | + +## Targets + +- Android: APK/AAB, internal distribution or managed store +- iOS: TestFlight, Apple Business Manager, or MDM + +## Required Checks + +- Static analysis +- Unit/widget tests +- Push registration test +- WebView session test +- Biometric blocking test +- Audit log verification diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100755 index 0000000..d036224 --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../app" +flutter pub get diff --git a/scripts/build-android.sh b/scripts/build-android.sh new file mode 100755 index 0000000..8d696d7 --- /dev/null +++ b/scripts/build-android.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../app" +flutter build apk diff --git a/scripts/build-ios.sh b/scripts/build-ios.sh new file mode 100755 index 0000000..5a867cb --- /dev/null +++ b/scripts/build-ios.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../app" +flutter build ios --no-codesign diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..c368c5a --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../app" +flutter analyze +flutter test