feat/dedicated-portal #6

Merged
elirtf merged 23 commits from feat/dedicated-portal into main 2026-06-18 20:40:56 +00:00
Owner
No description provided.
scripts/install.sh provisions a Docker Compose deployment end to end: checks prerequisites, generates .env with strong secrets, wires automatic TLS for a domain (or plain :8080 locally), then builds and waits for health. docker-compose.prod.yml publishes Caddy on 80/443 and persists certs. README gains a concrete production-deployment walkthrough.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rewrite jargon-heavy explanations into plain language a non-technical business owner can follow, keeping the terse tone. Tech tag chips left intact as design elements.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Admins now sign in to a client roster (/portal/clients) and drill into a per-client command center showing tickets & SLA, devices & alerts, billing, and licenses/contacts/contracts on one page; an aggregate 'all clients' overview remains. Adds org_summary/command_center_data helpers, a redirecting CSRF-checked client selector, a persistent client-scope eyebrow on every portal page, expanded dashboard stats (licenses, invoices), and a unified empty-state component across list pages. Client users keep the streamlined dashboard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tickets and Invoices nav items now show active-ticket and unpaid-invoice counts (amber), scoped to the selected client or aggregated across all clients. Counts collapse to a corner dot when the sidebar is icon-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
KPI labels/values, roster totals, scope pill, nav badges, section headings, pills and SLA chips now stay on a single line, truncating with an ellipsis only where horizontal space is genuinely tight instead of wrapping. The client-scope pill name is wrapped in a span so it ellipsizes cleanly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds an admin Integrations page showing, per connector (Microsoft 365 / SentinelOne / Meraki): whether credentials are set, which clients are mapped to a tenant/site, and a Test connection button that runs a live probe and reports the exact cause of failure — missing mapping, bad secret, or missing admin consent — instead of silently falling back to demo numbers. Implements Graph user counts (surfaced in the client command center) and documents that credentials require a per-client mapping.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a DB-backed settings store (config.py) with environment fallback and a Fernet-encrypted secret column (crypto.py, keyed off SETTINGS_SECRET/JWT_SECRET), so Microsoft 365 / SentinelOne / Meraki credentials are entered and edited on the Integrations page instead of .env — secrets never stored in plaintext, changes take effect without a restart. integrations.py now reads credentials at call-time; the page gains per-connector credential forms (secrets masked, blank = keep), Save and Disconnect actions, and the existing Test connection. Existing env vars still work as a fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the GUI config to general settings: a new Settings page (/portal/settings) with Branding & contact, Email/SMTP and Payments/Stripe sections, all stored in the DB (secrets encrypted) with env fallback. helpers.py now reads contact/branding via lazy template globals and SMTP/Stripe/base-URL via config.get() at call-time; tickets/marketing/invoicing/maintenance routes updated to match. Contact/branding edits reflect on the public site immediately, no restart.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Makes integrating self-explanatory: each connector shows what it powers, a collapsible 'where do I find these?' setup guide (Entra/SentinelOne/Meraki steps + links), a 3-step flow (credentials → test → map), and inline per-client tenant/site/network mapping (POST /portal/integrations/map) so the whole setup happens on one page. Adds a 'Send test email' button on Settings (helpers.send_test_email, synchronous, reports the real SMTP error).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rewrites the settings table to separate env-only bootstrap vars (JWT_SECRET, SETTINGS_SECRET, ADMIN_*, COOKIE_SECURE, DATA_DIR/UPLOAD_DIR) from the branding/SMTP/Stripe/integration settings now managed in the Settings and Integrations pages. Updates the production 'finish configuring' steps, portal-features note, troubleshooting, and the configuration section accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds an invoice builder (line items, quantity, unit price, tax rate, terms, auto invoice number, live total) that computes the amount and stores items as JSON, plus a branded standard-format PDF at /portal/invoices/{id}/pdf (weasyprint) following the conventional layout — seller/bill-to, line-item table, subtotal/tax/total, payment terms and pay-online link. Business name/address are GUI settings. The existing Stripe pay flow works unchanged off the computed total. Uploaded-PDF invoices still supported.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Trim the Settings/Integrations page ledes to just the functional info, and de-duplicate the README down to the single 'Configuration: GUI vs environment' section instead of restating it in the settings table, API integrations, and production steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
config.get() no longer reads environment variables — application settings (branding, SMTP, Stripe, integration credentials and per-client mappings) come solely from the GUI/DB. Removes the legacy GRAPH_TENANT_MAP/S1_SITE_MAP/MERAKI_NET_MAP env maps, the 'from .env' source badge, and trims .env.example to bootstrap/infra only (JWT_SECRET, SETTINGS_SECRET, ADMIN_*, COOKIE_SECURE, operational tunables).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The primary .btn was a light-blue gradient that washed out against the translucent header and blue background — brighten to a near-white→frost fill with very dark text and a stronger shadow so it reads on any background; give the ghost variant a visible fill/border too. The contact form had no autocomplete/id/labels, so browsers wouldn't offer autofill — add autocomplete tokens (name/email/tel/organization), ids and aria-labels.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the core PSA billing loop: time logged on tickets is now billable (with an optional per-entry rate and a default hourly rate setting), and admins can roll a client's unbilled billable time into a detailed invoice — one line item per entry — from the Invoices page, which surfaces unbilled hours per client. Entries are marked invoiced so they're never double-billed. TimeEntry gains billable/rate/invoice_id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a homepage section explaining the platforms we standardize on and why (NinjaOne RMM, SentinelOne EDR, Microsoft 365/Entra ID, Cisco Meraki), and adds NinjaOne/SentinelOne to the marquee. Rewrites the hero WAN-latency chart to behave like a real monitoring graph — a calm, mostly-stable line in a healthy band with gridlines, smoothing and a current-value dot — instead of the old erratic random walk.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Security page (/portal/security): posture score (Microsoft Secure Score or a composite of MFA adoption + patch compliance penalized by open incidents), threat overview, patch compliance, real local MFA-adoption tracking, and recent security events — all org-scoped, fed by Microsoft Graph + SentinelOne with graceful degradation (integrations.security_stats). Hardware page now shows lifecycle health, warranty status, purchase/EOL dates and assigned user; adds HardwareItem.eol_date. Documents the security data sources and Huntress roadmap in INTEGRATIONS.md, and updates it for GUI-managed encrypted credentials.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recurring managed-services agreements (Contract model) with monthly/quarterly/annual cycles that auto-generate invoices on schedule (billing.py + a daily scheduler thread, idempotent per day) and a /portal/agreements UI to create/pause/resume/invoice-now/run-billing. A /portal/reports financial dashboard: MRR/ARR, invoiced-vs-collected revenue by month, AR aging, revenue by client, recurring-vs-one-off mix, and a cash-flow forecast from MRR (CSS charts, no JS lib). Slack/Teams incoming-webhook notifications for ticket events via helpers.team_alert, configured under Settings → Chat notifications with a Send-test-message button. Documents agreement/report conventions and chat setup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Turns the Microsoft integration from bare counts into real monitoring: a Devices page (/portal/devices) lists each Intune-managed device with its owner, OS, compliance state, encryption status and last check-in, plus KPI alerts for non-compliant, stale (>14d) and unencrypted devices. integrations.managed_devices()/graph_managed_devices() fetch the per-device inventory with a demo fallback so the view is meaningful before Microsoft is connected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Devices view gains last-logon user, IP, MAC, ownership, storage and serial fields (Intune-native where available; IP/last-logon are RMM-sourced, shown via demo until connected), a search + compliance filter, and a column chooser persisted in localStorage. Sidebar nav is reorganized into collapsible groups — Support, Assets & security, Billing (Invoices/Agreements/Contracts/Documents/Reports), Admin — with per-group open state remembered and always-expanded on the narrow icon sidebar; group headers carry attention badges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Secret credentials (integration keys, SMTP/Stripe/chat secrets) can only be viewed or changed by an admin with two-factor enabled — secret fields render a 'Enable two-factor' lock otherwise, and the save routes drop/refuse secret writes server-side without MFA. Adds an eye toggle to reveal/hide what's typed into secret fields. Tests cover the gate (no-MFA admin can't store a key) with a new make_admin_mfa helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Merge branch 'main' of https://git.willowcrest.world/elirtf/msp into feat/dedicated-portal
Some checks failed
CI / lint-and-test (push) Has been cancelled
CI / docker-build (push) Has been cancelled
CI / lint-and-test (pull_request) Has been cancelled
CI / docker-build (pull_request) Has been cancelled
47e518ded0
elirtf merged commit a5381a5fad into main 2026-06-18 20:40:56 +00:00
elirtf deleted branch feat/dedicated-portal 2026-06-18 20:40:56 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
elirtf/msp!6
No description provided.