Commit Graph

36 Commits

Author SHA1 Message Date
Claude VM 377b88c48d feat(sync): auto-trigger PMTiles rebuild after sync + fix progress display
- Add pmtiles-webhook.ts shared helper for triggering PMTiles rebuild
- sync-county: trigger rebuild when new features synced, pass jobId to
  syncLayer for sub-progress, update % after UAT completion (not before)
- sync-all-counties: same progress fix + rebuild trigger at end
- geoportal monitor: use shared helper instead of raw fetch
- weekend-deep-sync + auto-refresh: consolidate webhook code via helper
- docker-compose: default N8N_WEBHOOK_URL to pmtiles-webhook on satra:9876

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:59:18 +03:00
AI Assistant 9bf79a15ed fix(geoportal): proxy PMTiles through HTTPS + fix click/selection + optimize rebuild
PMTiles was loaded via HTTP from MinIO (10.10.10.166:9002) on an HTTPS page,
causing browser mixed-content blocking — parcels invisible on geoportal.

Fixes:
- tile-cache nginx proxies /pmtiles/ → MinIO with Range header support
- PMTILES_URL changed to relative path (resolves to HTTPS automatically)
- clickableLayers includes PMTiles fill layers (click on parcels works)
- Selection highlight uses PMTiles source at z13+ (was Martin z17+ only)
- tippecanoe per-layer zoom ranges (terenuri z13-z18, cladiri z14-z18)
  skips processing millions of features at z0-z12 — faster rebuild

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 14:56:49 +03:00
AI Assistant aac93678bb fix(geoportal): move PMTILES_URL + MARTIN_URL to build args (NEXT_PUBLIC_ requires build time)
NEXT_PUBLIC_ env vars are inlined by webpack at build time in client components.
Setting them only in environment (runtime) has no effect — the map-viewer
was falling back to Martin for ALL tiles, causing 90% PostgreSQL CPU.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:30:26 +02:00
AI Assistant 9bab9db4df feat(geoportal): N8N webhook on sync completion + tile cache monitoring
- weekend-deep-sync.ts: fire webhook to N8N_WEBHOOK_URL after each sync cycle
  (N8N triggers tippecanoe PMTiles rebuild via SSH on host)
- nginx tile-cache: add stub_status at /status, custom log format with cache status
- Add tile-cache-stats.sh: shows HIT/MISS ratio, cache size, slow tiles
- docker-compose: add N8N_WEBHOOK_URL env var

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 09:44:38 +02:00
AI Assistant 0d5fcf909c feat(geoportal): PMTiles for terenuri/cladiri overview + cache warming + cleanup
- Extend PMTiles to include simplified terenuri (5m tolerance) and cladiri (3m)
- map-viewer: terenuri z13 from PMTiles, z14+ from Martin (live detail)
- map-viewer: cladiri z14 from PMTiles, z15+ from Martin
- Martin sources start at higher minzoom when PMTiles active (less DB load)
- Add warm-tile-cache.sh: pre-populate nginx cache for major cities
- Rebuild script now includes cache warming step after PMTiles upload
- Remove deprecated docker-compose version: "3.8"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:46:47 +02:00
AI Assistant 0572097fb2 feat(geoportal): activate PMTiles overview tiles from MinIO
UAT + administrativ layers now served from pre-generated PMTiles (~5ms)
instead of Martin/PostGIS (~200-2000ms) for zoom levels 0-14.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:51:57 +02:00
AI Assistant 536b3659bb feat(geoportal): nginx tile cache + PMTiles overview layers + tippecanoe pipeline
- Add nginx reverse proxy cache in front of Martin (2GB, 1h TTL, stale serving, CORS)
- Martin no longer exposes host port — all traffic routed through tile-cache on :3010
- Add PMTiles support in map-viewer.tsx (conditional: NEXT_PUBLIC_PMTILES_URL env var)
  - When set: single PMTiles source for UAT + administrativ layers (z0-z14, ~5ms/tile)
  - When empty: fallback to Martin tile sources (existing behavior, zero breaking change)
- Add tippecanoe Docker service (profiles: tools) for on-demand PMTiles generation
- Add rebuild-overview-tiles.sh: ogr2ogr export → tippecanoe → MinIO atomic upload
- Install pmtiles npm package for MapLibre protocol registration

Performance impact:
- nginx cache: 10-100x faster on repeat tile requests, zero PostGIS load on cache hit
- PMTiles: sub-10ms overview tiles, zero PostGIS load for z0-z14

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:28:49 +02:00
AI Assistant 675b1e51dd fix(martin): bake config into image via Dockerfile (Portainer volume mount fix)
Portainer CE deploys only docker-compose.yml — ./martin.yaml not present on host,
so Docker creates an empty directory instead of mounting the file. Solution: COPY
martin.yaml into the image at build time, eliminating the volume dependency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:18:30 +02:00
AI Assistant a83f9e63b9 fix(martin): correct Docker image tag to 1.4.0 (no v prefix for v1.x+)
Martin changed tag format at v1.0: v0.15.0 → 1.4.0 (dropped the v prefix).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:06:59 +02:00
AI Assistant a75d0e1adc fix(geoportal): mount Martin config + upgrade v1.4 + enable building labels
Root cause: martin.yaml was never mounted in docker-compose.yml — Martin ran
in auto-discovery mode which dropped cadastral_ref from gis_cladiri tiles.

Changes:
- docker-compose: mount martin.yaml, upgrade Martin v0.15→v1.4.0, use --config
- map-viewer: add cladiriLabel layer (cadastral_ref at z16+), wire into visibility
- martin.yaml: update version comment
- geoportal/: tile server evaluation doc + 3 skill files (vector tiles, PMTiles, MapLibre perf)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:28:20 +02:00
AI Assistant 3b456eb481 feat(parcel-sync): incremental sync, smart export, auto-refresh + weekend deep sync
Sync Incremental:
- Add fetchObjectIds (returnIdsOnly) to eterra-client — fetches only OBJECTIDs in 1 request
- Add fetchFeaturesByObjectIds — downloads only delta features by OBJECTID IN (...)
- Rewrite syncLayer: compare remote IDs vs local, download only new features
- Fallback to full sync for first sync, forceFullSync, or delta > 50%
- Reduces sync time from ~10 min to ~5-10s for typical updates

Smart Export Tab:
- Hero buttons detect DB freshness — use export-local (instant) when data is fresh
- Dynamic subtitles: "Din DB (sync acum Xh)" / "Sync incremental" / "Sync complet"
- Re-sync link when data is fresh but user wants forced refresh
- Removed duplicate "Descarca din DB" buttons from background section

Auto-Refresh Scheduler:
- Self-contained timer via instrumentation.ts (Next.js startup hook)
- Weekday 1-5 AM: incremental refresh for existing UATs in DB
- Staggered processing with random delays between UATs
- Health check before processing, respects eTerra maintenance

Weekend Deep Sync:
- Full Magic processing for 9 large municipalities (Cluj, Bistrita, TgMures, etc.)
- Runs Fri/Sat/Sun 23:00-04:00, round-robin intercalated between cities
- 4 steps per city: sync terenuri, sync cladiri, import no-geom, enrichment
- State persisted in KeyValueStore — survives restarts, continues across nights
- Email status report at end of each session via Brevo SMTP
- Admin page at /wds: add/remove cities, view progress, reset
- Hint link on export tab pointing to /wds

API endpoints:
- POST /api/eterra/auto-refresh — N8N-compatible cron endpoint (Bearer token auth)
- GET/POST /api/eterra/weekend-sync — queue management for /wds page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:50:34 +02:00
AI Assistant eab465b8c3 chore: add STIRLING_PDF_URL, STIRLING_PDF_API_KEY, PORTAL_ONLY_USERS to docker-compose
These env vars were previously hardcoded in source code and removed during
the production audit. Now properly configured in docker-compose.yml.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 06:46:38 +02:00
AI Assistant b38916229e fix(martin): add --default-srid=3844 (ST_Simplify views lose SRID metadata)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 22:05:19 +02:00
AI Assistant 1b679098ab fix(martin): revert to auto-discovery (Docker bind mount creates directories on Portainer)
Views already select only needed columns, so Martin auto-discovery
serves the same result without needing a config file.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 21:55:59 +02:00
AI Assistant ba3edc3321 fix(martin): mount config as /martin-config.yaml (Docker created /config/martin.yaml as directory)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 21:34:28 +02:00
AI Assistant 76c19449f3 perf(geoportal): zoom-dependent UAT simplification + Martin config + tile cache
PostGIS:
- gis_uats view: ST_SimplifyPreserveTopology(geom, 50) + only name/county/siruta
- gis_uats_simple view: ST_SimplifyPreserveTopology(geom, 500) for z0-z9

Martin config (martin.yaml):
- Explicit source definitions (auto_publish: false)
- gis_uats_simple (z0-9): only name+siruta, 500m simplified geometry
- gis_uats (z0-14): name+siruta+county, 50m simplified
- gis_terenuri (z10-18): object_id+siruta+cadastral_ref+area_value+layer_id
- gis_cladiri (z12-18): same properties
- 24h cache headers on all tiles

MapViewer:
- Dual UAT sources: simplified (z0-9) + detailed (z9+) with seamless handoff
- Zoom-interpolated paint: thin lines at z5, thicker at z12
- UAT labels only z9+, fill opacity z-interpolated (0.03→0.08)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:24:38 +02:00
AI Assistant 4a144fc397 fix(geoportal): use HTTPS Martin URL via Traefik /tiles proxy 2026-03-23 15:35:40 +02:00
AI Assistant 00a691debd chore: add NEXT_PUBLIC_MARTIN_URL env var for geoportal 2026-03-23 14:52:40 +02:00
AI Assistant c297a2c5f7 feat: add Geoportal module with MapLibre GL JS + Martin vector tiles
Phase 1 of the geoportal implementation:

Infrastructure:
- Martin vector tile server in docker-compose (port 3010)
- PostGIS setup SQL for GisUat: native geom column, Esri→PostGIS
  trigger, GiST index, gis_uats view for Martin auto-discovery

Geoportal module (src/modules/geoportal/):
- map-viewer.tsx: MapLibre GL JS canvas with OSM base, Martin MVT
  sources (gis_uats, gis_terenuri, gis_cladiri), click-to-inspect,
  zoom-level-aware layer visibility, layer styling
- layer-panel.tsx: collapsible sidebar with layer toggles
- geoportal-module.tsx: standalone page wrapper
- Module registered in config/modules.ts, flags.ts, i18n

ParcelSync integration:
- 6th tab "Harta" with lazy-loaded MapViewer (ssr: false)
- Centered on selected UAT

Dependencies: maplibre-gl v5.21.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 14:21:37 +02:00
AI Assistant 336c46ff8e chore: hardcode ANCPI ePay credentials in docker-compose
Portainer CE can't inject env vars, so credentials must be hardcoded
in the compose file (same pattern as all other secrets in the project).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:18:27 +02:00
AI Assistant 3921852eb5 feat(parcel-sync): add ANCPI ePay CF extract ordering backend
Foundation (Phase 1):
- CfExtract Prisma model with version tracking, expiry, MinIO path
- epay-types.ts: all ePay API response types
- epay-counties.ts: WORKSPACE_ID → ePay county index mapping (42 counties)
- epay-storage.ts: MinIO helpers (bucket, naming, upload, download)
- docker-compose.yml: ANCPI env vars

ePay Client (Phase 2):
- epay-client.ts: full HTTP client (login, credits, cart, search estate,
  submit order, poll status, download PDF) with cookie jar + auto-relogin
- epay-session-store.ts: separate session from eTerra

Queue + API (Phase 3):
- epay-queue.ts: sequential FIFO queue (global cart constraint),
  10-step workflow per order with DB status updates at each step
- POST /api/ancpi/session: connect/disconnect
- POST /api/ancpi/order: create single or bulk orders
- GET /api/ancpi/orders: list all extracts
- GET /api/ancpi/credits: live credit balance
- GET /api/ancpi/download: stream PDF from MinIO

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:09:52 +02:00
AI Assistant aab38d909c feat: add dedicated /api/address-book REST endpoint for inter-service access
Bearer token auth (ADDRESSBOOK_API_KEY) for external tools like avizare.
Supports GET (list/search/filter/by-id), POST (create), PUT (update), DELETE.
Middleware exclusion so it bypasses NextAuth session requirement.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 22:33:00 +02:00
AI Assistant f5deccd8ea refactor(pdf-compress): replace Ghostscript with qpdf + iLovePDF API
Ghostscript -sDEVICE=pdfwrite fundamentally re-encodes fonts, causing
garbled text regardless of parameters. This cannot be fixed.

New approach:
- Local: qpdf-only lossless structural optimization (5-30% savings,
  zero corruption risk — fonts and images completely untouched)
- Cloud: iLovePDF API integration (auth → start → upload → process →
  download) with 3 levels (recommended/extreme/low), proper image
  recompression without font corruption

Frontend: 3 modes (cloud recommended, cloud extreme, local lossless).
Docker: ILOVEPDF_PUBLIC_KEY env var added.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 17:50:46 +02:00
AI Assistant b079683a46 ui: rename email sender and subject to 'Alerte Termene' instead of ArchiTools
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 08:59:19 +02:00
AI Assistant 1cbdf13145 chore: add Brevo SMTP credentials and cron secret to docker-compose
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 08:22:06 +02:00
AI Assistant 974d06fff8 feat: add email notification system (Brevo SMTP + N8N daily digest)
- Add core notification service: types, email-service (nodemailer/Brevo SMTP), notification-service (digest builder, preference CRUD, HTML renderer)
- Add API routes: POST /api/notifications/digest (N8N cron, Bearer auth), GET/PUT /api/notifications/preferences (session auth)
- Add NotificationPreferences UI component (Bell button + dialog with per-type toggles) in Registratura toolbar
- Add 7 Brevo SMTP env vars to docker-compose.yml
- Update CLAUDE.md, ROADMAP.md, DATA-MODEL.md, SYSTEM-ARCHITECTURE.md, CONFIGURATION.md, DOCKER-DEPLOYMENT.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 01:12:36 +02:00
AI Assistant 5209fd5dd0 feat(dwg): DWG→DXF via sidecar microservice (libredwg)
Add dedicated dwg2dxf container (Debian slim + libredwg-tools + Flask)
instead of modifying the Alpine base image. The ArchiTools API route
proxies to the sidecar over Docker internal network.

- dwg2dxf-api/: Dockerfile + Flask app (POST /convert, GET /health)
- docker-compose.yml: dwg2dxf service, healthcheck, depends_on
- route.ts: rewritten from local exec to HTTP proxy
- .dockerignore: exclude sidecar from main build context

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:51:27 +02:00
AI Assistant 7cdea66fa2 feat: add parcel-sync module (eTerra ANCPI integration with PostGIS)
- 31 eTerra layer catalog (terenuri, cladiri, documentatii, administrativ)
- Incremental sync engine (OBJECTID comparison, only downloads new features)
- PostGIS-ready Prisma schema (GisFeature, GisSyncRun, GisUat models)
- 7 API routes (/api/eterra/login, count, sync, features, layers/summary, progress, sync-status)
- Full UI with 3 tabs (Sincronizare, Parcele, Istoric)
- Env var auth (ETERRA_USERNAME / ETERRA_PASSWORD)
- Real-time sync progress tracking with polling
2026-03-06 00:36:29 +02:00
Marius Tarau 4d094ffd1b fix: pass VIM_URL env var to container in docker-compose 2026-03-01 04:08:00 +02:00
AI Assistant d34c722167 feat(3.15): AI Tools extindere si integrare
Prompt Generator:
- Search bar cu cautare in name/description/tags/category
- Filtru target type (text/image) cu toggle rapid 'Imagine'
- 4 template-uri noi imagine: Midjourney Exterior, SD Interior,
  Midjourney Infographic, SD Material Texture (18 total)
- Config v0.2.0

AI Chat  Real API Integration:
- /api/ai-chat route: multi-provider (OpenAI, Anthropic, Ollama, demo)
- System prompt default in romana pt context arhitectura
- GET: config status, POST: message routing
- use-chat.ts: sendMessage() cu fetch real, sending state,
  providerConfig fetch, updateSession() pt project linking
- UI: provider status badge (Wifi/WifiOff), Bot icon pe mesaje,
  loading spinner la generare, disable input while sending
- Config banner cu detalii provider/model/stare

AI Chat + Tag Manager:
- Project selector dropdown in chat header (useTags project)
- Session linking: projectTagId + projectName on ChatSession
- Project name display in session sidebar
- Project context injected in system prompt

Docker:
- AI env vars: AI_PROVIDER, AI_API_KEY, AI_MODEL, AI_BASE_URL, AI_MAX_TOKENS
2026-02-28 04:51:36 +02:00
AI Assistant 11b35c750f 3.13 Tag Manager ManicTime sync bidirectional sync, backup, hierarchy validation
- ManicTime parser service: parse/serialize Tags.txt format, classify lines into project/phase/activity
- API route /api/manictime: GET (read + sync plan), POST (pull/push/both with backup versioning)
- ManicTimeSyncPanel component: connection check, stats grid, import/export/full sync with confirmation dialog
- Integrated into Tag Manager module with live sync status
- Docker: MANICTIME_TAGS_PATH env var, SMB volume mount /mnt/manictime
- Hierarchy validation: project codes, company association, duplicate detection
- Version bump to 0.2.0
2026-02-28 04:38:57 +02:00
AI Assistant 85bdb59da4 3.14 Password Vault encryption AES-256-GCM server-side
- Created src/core/crypto/ with AES-256-GCM encrypt/decrypt (PBKDF2 key derivation)
- Created /api/vault route: CRUD with server-side password encryption
- PATCH /api/vault migration endpoint to re-encrypt legacy plaintext passwords
- Rewrote use-vault hook to use dedicated /api/vault instead of generic storage
- Updated UI: amber 'not encrypted' warning  green 'encrypted' badge
- Added ENCRYPTION_SECRET env var to docker-compose.yml and stack.env
- Module version bumped to 0.2.0
2026-02-28 04:12:44 +02:00
AI Assistant 100e52222e fix(deploy): hardcode env vars in docker-compose to ensure they reach the container 2026-02-27 11:01:06 +02:00
AI Assistant ccba14a05e fix(deploy): add env vars to docker-compose, prisma generate in Dockerfile, move @prisma/client to deps 2026-02-27 10:43:32 +02:00
Marius Tarau cb5e01b189 Fix docker-compose for Portainer stack deploy
Remove env_file (.env not in repo) and proxy-network (not needed
yet). Inline essential environment variables directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:22:01 +02:00
Marius Tarau 4c46e8bcdd Initial commit: ArchiTools modular dashboard platform
Complete Next.js 16 application with 13 fully implemented modules:
Email Signature, Word XML Generator, Registratura, Dashboard,
Tag Manager, IT Inventory, Address Book, Password Vault,
Mini Utilities, Prompt Generator, Digital Signatures,
Word Templates, and AI Chat.

Includes core platform systems (module registry, feature flags,
storage abstraction, i18n, theming, auth stub, tagging),
16 technical documentation files, Docker deployment config,
and legacy HTML tool reference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 12:50:25 +02:00