Prisma tagged template literals were mangling regex backslashes.
Switch to $queryRawUnsafe for the complex regex queries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Node 22 (from 20): ~15% faster TypeScript compilation
- BuildKit cache mount on /root/.npm: npm ci reuses cached packages
between builds instead of re-downloading from registry
- NODE_OPTIONS --max-old-space-size=2048: prevents OOM on VMs with
limited RAM during Next.js build
Requires BuildKit enabled (default in Docker 23+, or set
DOCKER_BUILDKIT=1). Portainer CE uses BuildKit by default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous fix still used MAX(actualMax, counterVal) which meant a
stale counter (from entries deleted before the fix was deployed) would
override the actual entry count. Changed to use ONLY actualMax + 1.
The RegistrySequence counter is now just a cache that gets synced —
it never overrides the actual entries count.
Also added /api/registratura/debug-sequences endpoint:
- GET: shows all counters vs actual entry max (for diagnostics)
- POST: resets all counters to match actual entries (one-time fix)
After deploy, call POST /api/registratura/debug-sequences to reset
the stale counters, then delete the BTG-2026-OUT-00004 entry and
recreate it — it will get 00001.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move prisma generate before COPY . . so it's cached when only
source files change (saves ~10-15s per build)
- Use npm ci --ignore-scripts in deps stage (postinstall scripts
not needed, prisma generate runs explicitly)
- Combine apk add + addgroup + adduser into single RUN (fewer layers)
- Expand .dockerignore to exclude .claude/, .vscode/, logs, tsbuildinfo
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The old allocateSequenceNumber blindly incremented a counter in
RegistrySequence, which drifted out of sync when entries were deleted
or moved between companies — producing wrong numbers (e.g., #6 for
the first entry of a company).
New approach:
- Uses pg_advisory_xact_lock inside a Prisma interactive transaction
to serialize concurrent allocations
- Always queries the actual MAX sequence from KeyValueStore entries
(the source of truth) before allocating the next number
- Takes MAX(actual entries, counter) + 1 so the counter can never
produce a stale/duplicate number
- Upserts the counter to the new value for consistency
- Also adds recalculateSequence to DELETE handler so the counter
stays in sync after entry deletions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add min-h-0 + overflow-hidden on ScrollArea to enable scrolling
in the detail side panel (flex child needs bounded height)
- Wrap external status badge Tooltip in TooltipProvider to fix
"Tooltip must be used within TooltipProvider" runtime crash
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The multipart body parser was using the first \r\n\r\n as the file
content start, but this could miss the actual file part. Now properly
iterates through parts to find the one with filename= header, and
uses lastIndexOf for the closing boundary to avoid false matches
inside PDF binary data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ExternalStatusTracking types + ExternalDocStatus semantic states
- Authority catalog with Primaria Cluj-Napoca (POST scraper + HTML parser)
- Status check service: batch + single entry, change detection via hash
- API routes: cron-triggered batch (/api/registratura/status-check) +
user-triggered single (/api/registratura/status-check/single)
- Add "status-change" notification type with instant email on change
- Table badge: Radio icon color-coded by status (amber/blue/green/red)
- Detail panel: full monitoring section with status, history, manual check
- Auto-detection: prompt when recipient matches known authority
- Activation dialog: configure petitioner name + confirm registration data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Registratura: re-allocate number when company/direction changes on update,
recalculate old company's sequence counter from actual entries
- Extreme PDF: stream body to temp file instead of req.formData() to support large files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Company badges: US→U, SDT→S (B and G already single letter).
Direction: only intrat (↓ green) and iesit (↑ orange), removed intern since no longer used.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace full "BTG-0042/2026" with compact [B] ↓ 0042/2026 format:
- Colored company badge (B=blue, US=violet, SDT=green, G=gray)
- Direction arrow icon (↓ green=intrat, ↑ orange=iesit, ↔ gray=intern)
- Plain number without prefix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copies "nr. BTG-0042/2026 din 11.03.2026" to clipboard on click.
Small icon, subtle until hover, green check feedback on copy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
useMemo was called after early return (when deadline=null), violating
React Rules of Hooks. Moved all hooks before the conditional return.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ac-verificare (5z lucr.) now auto-track, created automatically with
any AC emitere type. Informational: authority notifies if incomplete.
- ac-emitere (30z cal.) now chains to ac-emitere-dupa-completari when
interrupted — term recalculates from completion submission date.
- ac-emitere-urgenta (7z lucr.) and ac-emitere-anexe (15z cal.) kept.
- New: ac-prelungire-emitere (15z lucr.) — authority communicates
decision on AC extension within 15 working days.
- Info box in DeadlineAddDialog for autorizare category explaining
auto-tracked verification + interruption mechanism.
- None of the autorizare deadlines have tacit approval.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously DIRECTION_CATEGORIES limited intrat to only completari+contestatie,
so cerere/aviz on intrat direction lost certificat/avize/urbanism/autorizare.
Now cerere/aviz doc types unlock all 6 categories on both directions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Typing {proiect}, {nr}, {an}, {detalii} or {text} in the subject field
now auto-transforms to template mode with the appropriate input widgets
(project dropdown, number fields, etc.).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add "Necesita analiza in comisie" toggle for avize category (mirrors CJ toggle)
- When OFF: auto-creates 5-day working limit for completari requests
- When ON: no limit (institution can request completions anytime)
- Add interruption mechanism: resolve aviz as "intrerupt" when institution
requests completions → auto-creates new 15-day deadline from completions date
- New resolution type "intrerupt" with yellow badge + chain support
- Restructure avize catalog entries:
- aviz-ac-15 (L50) and aviz-urbanism-30 (L350) now have chain to
aviz-emitere-dupa-completari for interruption flow
- aviz-mediu: updated hints about procedure closure prerequisite
- aviz-cultura-comisie: 2-phase with auto-track depunere la comisie (30 days)
- aeronautica, ISU, transport-eu: all get interruption chain
- 3 new auto-track entries: aviz-completari-limit (5zl), aviz-emitere-dupa-completari
(15zc), aviz-cultura-depunere-comisie (30zc)
- New document type: "Convocare sedinta"
- Info boxes in dialog explaining auto-track behavior + interruption mechanism
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix doc type showing "altele" after edit: preserve initial documentType
in allDocTypes map even if not in defaults or Tag Manager
- Filter deadline categories by document type: only cerere/aviz unlock
full permitting categories (CU, avize, urbanism, autorizare)
- Other doc types (scrisoare, notificare, etc.) only get completari +
contestatie as deadline categories
- Add completari to intrat direction (was missing)
- Pass documentType to DeadlineAddDialog for category filtering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Conex button now adds to linkedEntryIds (for clarificari/solicitari)
instead of setting threadParentId
- Inchide button sets threadParentId (direct reply) + auto-closes parent
- Fix Sterge button persistence bug: threadParentId now saves as empty
string instead of undefined (which was stripped in JSON serialization)
- Card headers: "Conex cu X" (amber) vs "Raspuns la X" (blue + green)
- Add conexTo prop to RegistryEntryForm for linked entry pre-fill
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix threadParentId clear: always show "Sterge" button even when parent not found in allEntries
- Bigger clear button with text label instead of tiny X icon
- Fallback display when parent not in current list (shows truncated ID)
- Close via conex: table/detail "Inchide" now creates a new reply entry that closes the original
- Header shows "Conex la BTG-XXX" + "Inchide originala" badge when closing via conex
- After saving the new conex entry, parent is auto-closed with resolution "finalizat"
- onClose signature changed from (id: string) to (entry: RegistryEntry) across table + detail
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Conex button on table rows (Reply icon, blue) — opens new entry with threadParentId pre-set + flipped direction
- Conex button on detail panel — same behavior
- Inchide button on table rows (CheckCircle2 icon, green) — only for open entries
- replyTo prop on RegistryEntryForm: pre-sets threadParentId + direction flip (intrat→iesit, iesit→intrat)
- Card header shows "Conex la BTG-0042/2026" with blue badge when replying
- Completari moved to last position in deadline category order
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove publicitate/comunicare category entirely (AC publicity handled by AC validity tracker)
- comunicare-aviz-beneficiar moved to auto-track: created alongside any iesit deadline
- Late receipt badge on incoming aviz entries: shows "Primit cu X zile intarziere" when document date < today
- Valabilitate document + AC Validity Tracker visible only when documentType is "aviz" (act administrativ)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CU has NO tacit approval on any entry
- Direction-dependent categories: iesiri (CU, Avize, Completari, Urbanism, Autorizare), intrari (Contestatie)
- Rename: Analiza → Urbanism (PUD/PUZ/PUG), Autorizare (AC) → Autorizare (AD/AC)
- Auto-track deadlines: cu-verificare (10zl) created automatically with CU emitere
- CJ toggle: auto-creates arhitect-sef solicita aviz (3zc) + primar emite aviz (5zc)
- Verification badge: after 10 days shows "Nu mai pot returna documentatia"
- Prelungire helper: CU issue date + 6/12/24 month calculator
- cu-prelungire-emitere changed to 30zc (practica administrativa)
- New DeadlineTypeDef fields: autoTrack, directionFilter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Comunicare, Instiintare under scrisoare
- Add Memoriu justificativ, Studiu de fezabilitate, Audit energetic, Caiet de sarcini under raport
- Add Aviz racordare, Acord unic under aviz
- Add Contract proiectare, PV predare-primire under contract
- Add Borderou, Fisa tehnica, Tema de proiectare, Deviz general, Conventie under altele
- Total seed templates: ~55 across 11 document types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add SEED_TEMPLATES catalog (11 doc types x 2-4 templates = ~30 predefined patterns)
- Add {proiect} field type with mini-autocomplete from Tag Manager projects
- Pre-fill {an} fields with current year on template selection
- Dynamic placeholder changes based on documentType + direction (22 combinations)
- Dropdown on empty focus: "Sabloane recomandate" + "Recente" sections
- Direction-aware tooltip on Subiect field (intrat vs iesit examples)
- getRecommendedTemplates() merges seeds + DB-learned, DB takes priority
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New subject-template-service: extracts reusable templates from existing
subjects by detecting variable parts (numbers, years, text after separators)
- Template input component: inline editable fields within static text
(e.g., "Cerere CU nr. [___]/[____] — [___________]")
- Two-tier autocomplete dropdown: templates sorted by frequency (top) +
matching existing subjects (bottom)
- Learns from database: more entries = better suggestions
- Follows existing contact autocomplete pattern (focus/blur, onMouseDown)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- "Bune practici" button in registry header opens a popover with internal rules
(numerotare, completare, termene, atașamente, închidere)
- Info tooltips on form labels: Direcție, Tip document, Subiect, Expeditor,
Destinatar, Atașamente (consistent with existing pattern on Data document)
- Install shadcn/ui Popover component
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The client page rendered inside AppShell layout, causing a flash of the
full app UI before redirecting to Authentik. The new route handler
initiates the OAuth flow server-side (CSRF token + POST to NextAuth
provider signin) and redirects instantly — no visible page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>