Commit Graph
100 Commits
Author SHA1 Message Date
MythEclipseandClaude 7423e4d83b fix(tauri): use raw __TAURI_INTERNALS__ invoke, fix dynamic import on Android
Root cause: dynamic import('@tauri-apps/plugin-opener') silently fails on
Android Tauri WebView because the module resolution path for @tauri-apps/api
(plugin dependency) differs from npm expectations in the bundled context.

Rewrote tauri.ts to use window.__TAURI_INTERNALS__.invoke() directly:
- openUrl() → invoke('plugin:opener|open_url', {url})
- setupDeepLinkHandler() → invoke('plugin:deep-link|get_current')
- Warm-start listener still uses import('@tauri-apps/api/event') for
  deep-link://new-url events (bundled as separate chunk by Vite)
- Added @tauri-apps/api as direct dependency

Also kept withGlobalTauri: true (needed for __TAURI_INTERNALS__ injection)
but reverted APK frontendDist back to bundled React app (../web/dist)
since redirect-to-live-web approach was unreliable.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 04:34:13 +07:00
MythEclipseandClaude 4b252a1d5d fix(tauri): enable withGlobalTauri so Tauri APIs work on live web
Without this, the redirect page loads zeavisedu.asepharyana.my.id but
__TAURI_INTERNALS__ is not injected, so isTauri() returns false,
handleGoogleLogin uses window.location.href (WebView navigation), and
Google blocks embedded WebView since 2016.

With withGlobalTauri=true, the live web page detects Tauri, uses tauri-
plugin-opener to open system browser, and Google OAuth works.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 04:01:38 +07:00
MythEclipseandClaude 7148e1026e feat(android): APK loads live web, fix cold-start deep links for Google OAuth
APK architecture change: replaces bundled React SPA with minimal redirect
page that always loads live web content. No more APK rebuilds for web changes.

Root cause of OAuth failure on Android:
1. Cold-start deep links lost — APK's old bundled JS called onOpenUrl()
   (warm-start listener only) but NOT getCurrent() which is required for
   cold-start deep links. Fix: redirect page + setupDeepLinkHandler both
   call getCurrent() before redirecting/navigating.
2. Session cookie was dropped — renderTauriDeepLinkPage returned a raw
   new Response() which overwrote the Set-Cookie header set by the
   callback handler. Fix: inject Set-Cookie into the Response.
3. tauri.conf.json frontendDist → "./web/dist-tauri" (redirect page)
4. Added @tauri-apps/plugin-deep-link and @tauri-apps/plugin-opener as
   web app deps so live-web imports work in Tauri WebView.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 03:47:22 +07:00
MythEclipseandClaude 96f337ef46 docs: add Tauri 2 Android and Rust ONNX Runtime sections
- New 'Platform' section detailing Tauri 2 Android app (WebView, Deep Link OAuth, Camera)
- Add Android CI/CD info, build commands, and GitHub Actions workflow reference
- Tagline updated to include 'Rust ONNX Runtime' and 'Tauri 2 Android'
- Architecture tree now shows apps/tauri/
- Components table: Android App row with Tauri 2, Rust, WebView, Deep Link OAuth
- Tech Stack: separate 'Inference Engine' section with Rust/Axum/ONNX Runtime bolded
- Prerequisites: Java 21 + Android SDK added
- Dev commands: tauri dev and tauri android dev included
- Cakupan updated: Web + Android (Tauri 2) now in-scope

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 02:58:52 +07:00
MythEclipseandClaude e2742a7a60 fix(auth): fix Android deep link intent URL format for Google OAuth
The intent:// URL in renderTauriDeepLinkPage was intent:/path (single slash),
producing zeavisedu:/login?token=xxx — a non-hierarchical URL that new URL()
cannot parse. Fixed to intent://login/path which produces a proper
hierarchical URI (zeavisedu://login/login?token=xxx).

Also hardened setupDeepLinkHandler to handle both double-slash (://) and
single-slash (:/) custom-scheme URLs as fallback.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 02:44:33 +07:00
MythEclipse d1275b5b65 fix(tauri): remove unused setup closure entirely 2026-06-16 02:04:07 +07:00
MythEclipse 12162fd6f7 fix(tauri): remove setup block that caused E0599 compile error
app.get_webview_window() needs tauri::Manager trait imported.
Removed the live URL redirect in setup for now — the bundled
frontend works fine. Can re-add later with proper imports.
2026-06-16 02:03:38 +07:00
MythEclipseandClaude 9ab8d41adf feat(android): generate launcher icons from zeavis-logo.svg during CI build
- Add scripts/generate-icons.js using sharp to convert SVG to PNG
  at all Android density buckets (mdpi 48→xxxhdpi 192)
- Add sharp as devDependency
- Update CI workflow to run icon generation after tauri android init
- Replaces Tauri's default icons with ZeaVis Edu logo

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 01:53:59 +07:00
MythEclipseandClaude 254fe19bb6 feat(android): always load live web URL so APK never needs rebuild for web changes
On Android, the app navigates to the live production URL immediately
after setup. The APK becomes a thin shell — bundled frontend is only
a placeholder for the ~1 second before redirect. All web updates
(deploy web) take effect instantly on all installed APKs.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 01:49:03 +07:00
MythEclipseandClaude 99acc43ff0 fix(android): use intent:// protocol for deep link return from system browser
Replace custom zeavisedu:// scheme in callback HTML with Chrome's
native intent:// protocol which directly opens the target Android app
by package name. Includes browser_fallback_url for non-app scenarios.

Also updates the HTML page with better UX: auto-redirect via JS,
fallback button, and copyable URL for manual paste.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 01:25:02 +07:00
MythEclipseandClaude 1afd2e013c fix(android): add deep link handler to intercept zeavisedu:// URLs and navigate WebView
Login-page won't auto-process token on deep link return because
the WebView stays on the page it was on. Added setupDeepLinkHandler()
which listens for zeavisedu:// scheme URLs and navigates the WebView
to the correct path+query.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 01:03:45 +07:00
MythEclipseandClaude e1732f5111 docs: enrich root README with full project plan details
- Add project plan context: team members, executive summary, schedule, risk management
- Add project scope, deliverables, and classification table with symptoms
- Add bibliography/references section from project plan
- Centered header with logo, emoji-section navigation
- Cleaner structure: Tentang → Tim → Ringkasan → Cakupan → Jadwal → Risiko → Arsitektur → Tech Stack → Memulai → Dokumentasi → Pustaka

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 00:25:47 +07:00
MythEclipseandClaude fc832b404e fix(auth): use VITE_API_BASE_URL for Google OAuth redirect instead of window.location.origin
On Tauri Android, window.location.origin = http://tauri.localhost
which is the embedded dev server URL, not the API server.
Use VITE_API_BASE_URL env var which points to the production API.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 00:23:46 +07:00
MythEclipseandClaude 6ba3deb149 docs: restructure all README.md into cohesive hierarchy
- Root README redesigned as landing page with 7 sub-chapters
- Each child README gets navigation header + footer linking back to root
- Cross-links between Machine_Learning, ml-service, and infra READMEs
- Reduced duplication: root summarizes, children provide full detail
- Net -207 lines, cleaner structure

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 00:23:18 +07:00
MythEclipseandClaude ac59548337 feat(android): Google OAuth via system browser + deep link for Android
Background: Google blocks OAuth in embedded WebView (403 disallowed_useragent).
Solution: open Google login in the Android system browser, then deep-link
back to the Tauri app via custom scheme after callback.

Changes:
- Tauri: add tauri-plugin-opener + tauri-plugin-deep-link to Cargo.toml
- Tauri: register plugins in lib.rs, add capabilities
- Web: auth-form.tsx Google button uses openUrl() via @tauri-apps/plugin-opener
  on Tauri (opens in system browser), falls back to window.location.href
- Web: add lib/tauri.ts for isTauri() detection + lazy opens
- API: /auth/google accepts ?platform=tauri → encodes into OAuth state param
- API: /auth/google/callback decodes state → if tauri, renders HTML page
  that deep-links back via zeavisedu:// scheme; if web, 302 redirect
- Android: patch script adds deep link intent filter for zeavisedu:// scheme

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 23:49:47 +07:00
MythEclipseandClaude d292bc4b3c feat(auth): add Google logo SVG to 'Masuk dengan Google' button
Inline SVG with official Google brand colors (blue, green, yellow, red)
placed before the label text with gap-2.5 spacing.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 23:17:46 +07:00
MythEclipseandClaude 787acf077f fix(vite): add data-cfasync="false" to script tags to prevent Cloudflare Rocket Loader breaking JS
Cloudflare Rocket Loader rewrites <script type="module"> to
<script type="randomhash-module"> which browsers can't parse,
causing complete blank page. data-cfasync="false" disables this.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 23:00:30 +07:00
MythEclipseandClaude 250355562f fix(login): replace useSearchParams with native URLSearchParams + loading spinner
- useSearchParams can lose params during re-renders, causing blank page
- Use native window.location.search + URLSearchParams instead (always accessible)
- Add oauthProcessing spinner state so user sees 'Menyelesaikan login...'
  instead of blank page while /auth/me is being called

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 22:38:11 +07:00
MythEclipseandClaude d47c73308e fix(auth): replace deprecated set.redirect with manual 302 Location header
Elysia's set.redirect returns 200 OK instead of 302 redirect on the
current version. Use set.status = 302 + set.headers['Location'] instead
for both /auth/google (Google OAuth redirect) and /auth/google/callback
(all redirect paths: errors, success token delivery).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 22:06:59 +07:00
MythEclipseandClaude 4b1d70d1c4 ci(deploy): inject Google OAuth env vars into VPS .env
Add GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URI
to the deploy workflow so the API can use Google OAuth on production.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 21:57:12 +07:00
MythEclipseandClaude c9ae90a042 feat(auth): implement Google OAuth callback with user auto-creation
API (apps/api/src/routes/auth.ts):
- Exchange authorization code for tokens via Google's token endpoint
- Decode id_token payload (JWT) to extract sub, email, name
- Find user by googleId → fall back to email match (link accounts)
- Auto-create user if neither found (role: 'user', no password)
- Create session + set cookie, redirect to /login?token=<token>

Web (apps/web/src/pages/login-page.tsx):
- Consume ?token= query param from OAuth redirect
- Store token in localStorage for future API calls
- Fetch /auth/me to hydrate Zustand store, then navigate to dashboard
- Show OAuth errors from ?error= query param

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 21:35:40 +07:00
MythEclipseandClaude a55b1521ea ci(android): run patch-android-manifest.sh after tauri android init
Ensures CAMERA permission is always injected into the generated
AndroidManifest.xml during CI builds.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 21:05:34 +07:00
MythEclipseandClaude a36b74a1cf feat(scan): add camera capture for Android with toggle between upload and live camera
- Add CameraCapture component with live viewfinder via getUserMedia
- Support rear/environment camera (default) with switch to front/user
- Capture to JPEG 92% quality via canvas, reuse existing upload flow
- Toggle between 'Unggah' (file upload) and 'Kamera' (live capture) modes
- Error handling for denied/not found/not readable in Bahasa Indonesia
- Add patch script for AndroidManifest CAMERA permission (gen/ is gitignored)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 20:54:11 +07:00
MythEclipseandClaude c881e6a2b2 fix(auth): pass request.headers to getCurrentUser in all protected routes
dashboard, diagnoses, expert routes now support Authorization header fallback for Android WebView

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 20:11:11 +07:00
MythEclipseandClaude 7693a02c98 fix(auth): add bearer token auth as fallback for Android WebView third-party cookie blocking
Android WebView blocks third-party cookies by default. This patch:
- Returns session token in login/register response body
- Stores token in localStorage, sends via Authorization: Bearer header
- Backend getCurrentUser supports Authorization header fallback

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 19:43:02 +07:00
MythEclipseandClaude 528a1622d0 fix(auth): prevent AuthInitializer from overwriting Zustand with null user
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 19:04:29 +07:00
MythEclipseandClaude 51a4cb9ed2 fix(auth): detect HTTPS via X-Forwarded-Proto for SameSite=None cookies, fix AuthGuard null overwrite
- Cookie SameSite now dynamic: None;Secure when behind HTTPS proxy, Lax otherwise
- AuthGuard useEffect no longer overwrites Zustand store with null from background refetch
- AuthInitializer: add staleTime 30s

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 18:17:26 +07:00
MythEclipse 22307d44de fix(api): add http://tauri.localhost to CORS allowed origins 2026-06-15 17:09:40 +07:00
MythEclipseandClaude 41e0501e6b fix(tauri): add absolute API base URL default and CORS origins for Android WebView
- Set VITE_API_BASE_URL default to production API URL in api-client.ts
  so fetch() uses absolute URLs instead of relative paths that fail on Tauri
- Add tauri://localhost and https://tauri.localhost to API CORS allowed origins
- Also fix .env WEB_APP_URL from stale .tech to .my.id

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 14:32:54 +07:00
MythEclipseandClaude f675b86dc8 fix(docker): remove port exposure from docker-compose.yml
All services route through Traefik via internal network labels.
No ports need to be exposed on the host.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 14:05:44 +07:00
MythEclipseandClaude 8ed1b57f1d fix(ci): add container wait loop before health check in deploy
Containers need time to start after docker compose up -d. Replaced
instant grep check with up-to-60s retry loop.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 14:04:19 +07:00
MythEclipseandClaude bf1725a4b8 fix(docker): remove non-existent shared/node_modules COPY from API Dockerfile
packages/shared has only devDependencies (typescript). After
bun install --production, packages/shared/node_modules does not
exist. Root node_modules contains all hoisted deps.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 13:58:23 +07:00
MythEclipseandClaude 8954535e08 fix(ci): add tauri package.json to Dockerfiles and fix Android NDK/build issues
Build and Deploy: workspace has 4 members (api/web/shared/tauri) but
Dockerfiles only copied 3 package.json files. Missing tauri workspace
member caused bun install --production to fail with frozen lockfile
error.

Build Android APK:
- Remove explicit NDK 28 install (runner has NDK 29 pre-installed, dual
  NDK presence broke ANDROID_NDK_HOME resolution)
- Auto-pin NDK version from runner's SDK
- rm -rf gen/android before tauri android init (stale cache recovery)
- Remove gen/android/.gradle from Gradle cache (causes stale state)
- Use --apk flag for faster APK-only build

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 13:54:55 +07:00
MythEclipseandClaude b93be6c6cb fix(docker): copy bun.lock and workspace node_modules to API runner stage
Bun workspace symlinks (apps/api/node_modules/*) pointed to root
.bun cache but were never copied from deps→runner. Added bun.lock,
apps/api/node_modules, and packages/shared/node_modules to the
runner COPY chain so  and  resolve at runtime.

Also added bun.lock to web Dockerfile for deterministic installs.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 03:30:18 +07:00
MythEclipseandClaude 2d39468279 perf(ci): add Bun and Gradle caching to Android workflow
Cache Bun dependencies (install cache + node_modules) and Gradle caches
(wrapper, dependencies, build artifacts) to dramatically speed up CI builds.
Gradle key uses Cargo.lock since gradle files don't exist at checkout time.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 01:43:25 +07:00
MythEclipseandClaude 78db3a03ac chore: change base URL to zeavisedu.asepharyana.my.id
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 01:35:58 +07:00
MythEclipseandClaude 03c1e4edb8 fix(ci): add tailwindcss as direct dependency
PostCSS plugin needs tailwindcss package available in node_modules
at build time. Adding it as a direct dependency ensures consistent
resolution.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 01:23:51 +07:00
MythEclipseandClaude 05055ed9cf fix(ci): remove bun.lock from Docker COPY to avoid version mismatch
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 01:17:25 +07:00
MythEclipseandClaude 02ae022174 fix(ci): regenerate bun.lock and disable frozen-lockfile in Dockerfiles
bun auto-enables --frozen-lockfile in CI by default. Use env var
BUN_INSTALL_FROZEN_LOCKFILE=0 to override this behavior. Also
regenerate lockfile fresh to ensure it is compatible with bun 1.3.14.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 01:06:17 +07:00
MythEclipseandClaude 9ee3af8a1f fix(ci): add --no-frozen-lockfile to bun install in Dockerfiles
bun defaults to --frozen-lockfile in CI environments, causing failures
when the lockfile format differs from the version used at build time.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 01:02:35 +07:00
MythEclipseandClaude 3d3ca72230 fix(ci): remove --frozen-lockfile to prevent bun version mismatch failures
CI uses bun 1.3.14 (stable) but local dev uses canary. Lockfile
format can differ between versions causing spurious failures.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 00:57:31 +07:00
MythEclipseandClaude 3d79b227d7 fix(ci): remove auto-commit to prevent infinite loop
Tag created by softprops/action-gh-release is the single source of truth.
Version bump in tauri.conf.json + Cargo.toml is local to the build only.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 00:26:12 +07:00
MythEclipseandClaude 853fee66b2 feat(ci): auto-increment version + publish to GitHub Release
- Compute version from latest git tag (bump patch)
- Update tauri.conf.json and Cargo.toml with new version
- Create GitHub Release with signed APK + AAB via softprops/action-gh-release
- Release name: v{version}, APK filename: zeavis-edu-v{version}.apk

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 00:16:32 +07:00
MythEclipseandClaude 360530fe1c fix(ci): add tauri android init step before build
gen/android/ is gitignored — must regenerate in CI.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 23:53:42 +07:00
MythEclipse ab61065502 feat(tauri): add tauri application 2026-06-14 23:39:31 +07:00
MythEclipseandClaude cc4a12aeb0 feat(ci): add GitHub Actions workflow for Android APK build
- Trigger on push to main (web/tauri/shared changes), PR, and manual
- Builds Vite frontend + Tauri Rust for 4 Android arches
- Signs APK with keystore from GitHub secrets
- Uploads signed APK + AAB as artifact

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 23:36:58 +07:00
MythEclipseandClaude d8e1b0b681 feat(tauri): add Tauri v2 Android app wrapper
- Wrap apps/web as Android APK via Tauri v2 WebView (zero web changes)
- Disable default compression feature to avoid brotli/alloc-no-stdlib conflict with Rust 1.96
- Add RGBA icon placeholders
- Add Android keystore to gitignore

APK output: apps/tauri/gen/android/app/build/outputs/apk/

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-14 23:16:58 +07:00
MythEclipseandClaude c116a2c4a5 fix(ml-service): test logic + prediction_response status forward
- calibrate_probs_selects_top_label: use logits that produce confidence >= 0.70
- prediction_response: forward status from Prediction struct instead of hardcode

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 17:08:27 +00:00
MythEclipseandClaude 9ab472ce1b fix(ml-service): add missing status field in PredictionResponse + fix unused variable
- PredictionResponse::status was missing in prediction_response()
- Prefix preprocess_start with underscore for unused variable warning

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 16:43:53 +00:00
MythEclipseandClaude 1aa8f9cd5f fix(ci): download model files from HF root path to correct subdirs
Files on HF hub sit at repo root (model.onnx, etc.),
not in model/ subfolder. Fix download script to copy
each file to the correct subdirectory expected by Docker.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 16:15:06 +00:00
MythEclipseandClaude 58d3feb8a0 fix(ml): fix cbam_block, cardinality, Lambda serialization + update CI download to include best_model.keras
- save_model.py: fix cbam_block channels dtype (x.shape[-1] not tf.shape)
- save_model.py: match notebook architecture (Resizing + GaussianNoise)
- save_model.py: load weights H5 instead of .keras (Lambda serialization safe)
- notebook: add output_shape to Lambda layers for Keras 3 compatibility
- notebook: fix n_bins NameError in temperature scaling plot
- notebook: fix cardinality fallback (or 100 → if card > 0 else 100)
- deploy.yml: download best_model.keras + calibration.json from HF
- HF repo: MythEclipse2737/zeavis-edu-corn-leaf-classifier

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 15:59:50 +00:00
MythEclipse aa58a0301a a 2026-06-12 15:24:49 +00:00
MythEclipse 2e925a4188 a 2026-06-12 15:24:49 +00:00
MythEclipse 731b5728f7 a 2026-06-12 15:24:49 +00:00
MythEclipse 1cf73aff6d b 2026-06-12 15:24:49 +00:00
MythEclipse 857a008087 a 2026-06-12 15:24:49 +00:00
MythEclipse f9bd991bdf feat(ml): implement v3.0 architecture with CBAM and calibrated inference
- Integrate Convolutional Block Attention Module (CBAM) for improved feature focus
- Implement temperature scaling and confidence-based status reporting
- Automate dataset acquisition using kagglehub
- Update ONNX opset to 18 and refine preprocessing validation
2026-06-12 15:24:49 +00:00
MythEclipseandClaude df09bbca89 fix(ci): download ONNX directly from HF Hub instead of full export pipeline
- No need to install TensorFlow (3GB) — just pip install huggingface_hub
- Download pre-built model.onnx directly (saved from notebook export)
- Cuts CI time from ~10 min to ~30 seconds

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 20:23:39 +00:00
MythEclipseandClaude 04d2bebdfe fix(ci): add HF_TOKEN diagnostic and grouped logging for ml build
- Verify HF_TOKEN exists before attempting download
- Group CI log output for readability
- Use os.environ['HF_TOKEN'] instead of .get() to fail fast

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 20:12:55 +00:00
MythEclipseandClaude 7f17c19dc8 fix(ci): download model from Hugging Face instead of storing in repo
- Remove binary model artifacts tracked in repo (.tflite, saved_model, tfjs model.json)
- CI now downloads best_model.keras from Hugging Face Hub (MythEclipse2737/corn-leaf-disease-classifier)
- Add save_model.py step before convert_onnx.py in CI pipeline
- Remove LFS patterns from .gitattributes (no longer needed)
- Remove lfs:true from checkout action

The model is fetched at CI time using HF_TOKEN secret — no large
binary files stored in git.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 20:05:55 +00:00
MythEclipse 8137057186 a 2026-06-11 19:42:02 +00:00
MythEclipse 4377be14cd chore(Machine_Learning): update notebook execution count and outputs 2026-06-11 16:49:37 +00:00
MythEclipse c733f3bfe1 a 2026-06-11 16:39:04 +00:00
MythEclipse 8c65e33a74 chore(Machine_Learning): clear notebook outputs and add .gitignore 2026-06-11 16:31:38 +00:00
MythEclipseandClaude 7a7e5b5955 fix: update Google Drive file ID to correct dataset link
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 15:19:38 +00:00
MythEclipseandClaude b83b2e132f feat: download dataset from Google Drive when running locally
- Add  dep to requirements.txt
- Non-Colab path: download dataset_jagung.zip from Drive using file ID
  if not present locally, then extract as usual
- Keeps Colab path unchanged (drive.mount)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 15:18:25 +00:00
MythEclipseandClaude ddced09bbc feat: make notebook dual-compatible (Colab + local)
- Add IS_COLAB auto-detection (try/except google.colab)
- Guard all /content/ paths behind IS_COLAB check
- Local paths resolve relative to Machine_Learning/ directory
- Remove unused imports (tarfile, pathlib, duplicate PIL)
- Consolidate sklearn imports into cell 2

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 15:17:32 +00:00
MythEclipseandClaude e791a71425 chore: trim requirements.txt to only ML pipeline deps, fix venv path, add .venv to gitignore
- requirements.txt: 230 → 11 top-level packages (removed transitive deps, CUDA/JAX/PyTorch/HuggingFace/Jupyter noise)
- CLAUDE.md: update venv setup to point at repo-root .venv
- .gitignore: add .venv/ and venv/ entries
- Memory: record venv location to avoid duplicate creation

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 15:14:55 +00:00
MythEclipseandClaude 837cfe933a feat: push deploy pipeline - auth, sidebar layout, ML artifacts, LFS
Notable changes:
- Add .gitattributes for LFS tracking on ML model artifacts
- Add AuthGuard to all protected routes + login/register/logout flow
- Add collapsible Sidebar replacing old Navbar
- Redesign MainLayout with sidebar + mobile header
- Add password show/hide toggle to AuthForm
- Add Logout button to MobileNav
- Update footer credit to ATLAS Project - Pijak x IBM SkillsBuild
- Update deploy.yml: generate ONNX in CI (vs HuggingFace download)
- Remove deprecated ML scripts (download/upload model .sh, .gitignore)
- Remove stale MEMORY.md
- Add ML model artifacts (TFLite, SavedModel, TFJS)
- Update notebook.ipynb training pipeline

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 20:26:48 +07:00
MythEclipse 3e2f04413e chore(ml): remove machine learning model files 2026-06-11 20:23:57 +07:00
MythEclipse 09602b3fe0 refactor(web): add value formatter to ChartCard component
Introduce a `valueFormatter` prop to the `ChartCard` component to allow
customized data presentation in tooltips. This enables more readable
units for specific metrics, such as converting bytes to MiB or
seconds to milliseconds.
2026-06-08 02:03:23 +07:00
MythEclipse b0dd1f289a chore(api): update uploader base URL domain
Update the default `uploaderBaseUrl` from `.tech` to `.my.id` due to the
previous domain being decommissioned.
2026-06-08 01:53:02 +07:00
MythEclipse 64dcfa70d8 feat(web): add client-side telemetry for API calls, errors, and scan operations 2026-06-08 01:23:51 +07:00
MythEclipse 89dcbe8fa2 feat(ml-service): add detailed ML observability metrics for inference, predictions, and errors 2026-06-08 01:21:47 +07:00
MythEclipse c45f771f24 feat(telemetry): add comprehensive Prometheus metrics and expand dashboard with system, API, ML, and Node.js runtime sections 2026-06-08 01:20:42 +07:00
MythEclipse b7a3c530a7 refactor(web): replace custom telemetry API with direct Prometheus queries
Rewrite the telemetry page logic to bypass the custom proxy API in
favor of direct Prometheus queries.

- Implement `queryRange` and `queryInstant` helpers for Prometheus API
- Replace `TelemetryAPI` client with direct fetch calls to Prometheus
- Update data fetching logic to use standard Prometheus query parameters
- Simplify state management and data transformation for charts
2026-06-08 01:07:13 +07:00
MythEclipse 26f99fa4d4 feat(web): compute memory usage client-side and add app-specific metrics to telemetry dashboard 2026-06-08 00:54:59 +07:00
MythEclipse f5ac0a8795 feat(web): implement telemetry dashboard with data visualization
Add a comprehensive telemetry dashboard page featuring real-time
system statistics and metric visualization using recharts.

- Integrate recharts for area and bar chart rendering
- Implement TelemetryAPI client for stats, discovery, and chart data
- Add dashboard UI with stat cards and responsive charts
- Remove legacy nginx sub_filter proxy configuration in favor of
  direct API communication to telemetry.imrnes.team
2026-06-08 00:31:30 +07:00
MythEclipse 65d0040c0d fix(web): escape quotes in sub_filter for fetch calls
Update the sub_filter pattern for fetch requests to include escaped
double quotes. This ensures that path rewriting correctly handles
JavaScript fetch calls that use double-quoted strings, preventing
broken resource paths in the telemetry dashboard.
2026-06-08 00:11:02 +07:00
MythEclipse 4589766f27 build(web): switch to alpine-based nginx runner for sub_filter support
Migrate the web runner stage from the official nginx alpine image to a
standard alpine image with the nginx package installed. This ensures
the presence of the `http_sub_module` required for path rewriting in
the telemetry proxy configuration.

- Replace `nginx:1.27-alpine` with `alpine:3.20` and `apk add nginx`
- Update Nginx configuration file path to `/etc/nginx/http.d/default.conf`
- Update web asset root directory to `/var/lib/nginx/html`
- Add `X-Forwarded-For` and `X-Forwarded-Proto` headers to proxy locations
2026-06-08 00:00:33 +07:00
MythEclipse 4dde9d8408 refactor(web): implement nginx reverse proxy for telemetry dashboard
Transition telemetry dashboard integration from an external URL approach to a local reverse proxy via Nginx. This simplifies client-side connectivity by routing all telemetry requests through the existing web server's domain.

- Configure Nginx to proxy `/telemetry/` sub-paths to the internal telemetry service
- Implement `sub_filter` in Nginx to rewrite root-relative paths for the SPA
- Remove `VITE_TELEMETRY_URL` build arguments and environment variable dependencies
- Simplify `TelemetryPage` to use a relative `/telemetry` base path
- Clean up deployment workflows and Dockerfile by removing unused telemetry build args
2026-06-07 23:44:57 +07:00
MythEclipse 9602a64e18 feat(web): externalize telemetry URL via environment variables
Replace the hardcoded Nginx proxy configuration with a dynamic environment variable approach. This allows the telemetry dashboard to be loaded via a public URL instead of relying on a local Tailscale proxy.

- Add `VITE_TELEMETRY_URL` build argument to Dockerfile
- Pass `VITE_TELEMETRY_URL` through GitHub Actions deployment workflow
- Remove `/telemetry/` location block from nginx.conf
- Update `TelemetryPage` to use the new environment variable and improve iframe loading state management
2026-06-07 23:31:15 +07:00
MythEclipse cd93d1a06d feat(web): add telemetry dashboard page with nginx proxy and nav integration 2026-06-07 23:21:40 +07:00
MythEclipse 0d458d9437 chore(telemetry): update subproject to latest commit 2026-06-07 23:04:22 +07:00
MythEclipse c0533f3ed9 feat(infra): add deployment architecture docs and remove unused DNS secrets from telemetry workflow 2026-06-07 23:02:35 +07:00
MythEclipse 2ade67170c feat(ci): add node-exporter cleanup and health check to deploy workflow 2026-06-07 22:59:44 +07:00
MythEclipse 204dd0311b feat(ci): add telemetry CI/CD workflow for build and deploy to Orange VPS 2026-06-07 22:58:43 +07:00
MythEclipse 420dc4725b feat: add Node Exporter service for system metrics scraping in docker-compose 2026-06-07 22:55:03 +07:00
MythEclipse b3494e2a9b fix: force-remove containers before docker compose up 2026-06-07 22:30:45 +07:00
MythEclipse 02fbb56492 fix: docker compose down before up to clear container name conflicts 2026-06-07 22:27:48 +07:00
MythEclipse ff5e5fd091 fix: add --force-recreate to docker compose up in deploy 2026-06-07 22:24:49 +07:00
MythEclipseandClaude Opus 4.8 0fc305f21b fix: create telemetry-net on deploy to fix docker compose up
App services reference telemetry-net as external, but telemetry runs
on a separate VPS. Creating the network as empty on the app VPS so
docker compose up doesn't fail.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 22:21:31 +07:00
MythEclipseandClaude Opus 4.8 521aaa184e fix: handle local VPS changes during deploy by using git reset --hard instead of pull
Switches from git pull --ff-only to git fetch + git reset --hard
origin/main to avoid failing when VPS has uncommitted local changes
to tracked files (apps/ml-service/Dockerfile, docker-compose.yml).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 22:18:17 +07:00
MythEclipseandClaude Opus 4.8 685cf0955b fix: sync bun.lock with package.json changes
The lockfile was out of sync causing Docker builds to fail with
'lockfile had changes, but lockfile is frozen' on CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 22:14:14 +07:00
MythEclipse 64567986e1 feat: update ML service Dockerfile to archlinux base and add port bindings for api/ml metrics 2026-06-07 21:40:09 +07:00
MythEclipse 6933e5512f docs(telemetry): separate production cross-VPS and local dev architecture docs 2026-06-07 21:15:32 +07:00
MythEclipse 7e0e052200 docs: clarify telemetry stack local-dev vs production separation in docker-compose.telemetry.yml 2026-06-07 21:13:15 +07:00
MythEclipse 36216601e3 docs: add telemetry stack documentation to CLAUDE.md, METRICS.md, and README.md 2026-06-07 21:00:22 +07:00
MythEclipse 2c41b80f97 feat: expose /metrics endpoint and add telemetry ClickHouse credentials 2026-06-07 20:57:45 +07:00
MythEclipseandClaude Opus 4.8 0da578c546 chore: add bun.lock, docker-compose telemetry network, and METRICS.md documentation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 18:14:35 +07:00