Skip to content

Releases: XenPool/ipsolis

ip·Solis v0.7.1

Choose a tag to compare

@github-actions github-actions released this 16 Jul 09:35

Added

  • Air-gapped runtime. The browser now loads nothing from external CDNs — all CSS, JavaScript
    and fonts are served from the ipSolis host. Tailwind is compiled during the Docker image build (a
    node:20-alpine stage) into a local stylesheet; htmx, the Monaco script editor (whole vs/ tree)
    and the Inter font are vendored under /static/vendor/. Internet is required only to build the
    image or docker pull a prebuilt one. Optional CSP_ENABLED flag adds a self-only
    Content-Security-Policy; a CI guard fails the build if any external asset origin reappears. No
    visual/behaviour change (one pre-existing latent bug fixed: the standalone auth pages now render
    their surface colors). See the new air-gapped runtime note in the deployment guide.
  • Order justification. A free-text business justification, configurable per asset definition
    (collect on/off + required yes/no), shown to the approver on the decision page and in the approval
    email / Teams / Slack notifications.
  • Portal execution-step visibility, per asset definition. off (default — status only),
    detailed (step names/status/timing), or debug (adds raw step logs/errors for diagnostics).

Fixed

  • External-secret resolution for SMTP. The worker's email send path now resolves an
    email.password stored as a vault://… / ccp://… reference (previously only the Test SMTP
    button did, so an externalized SMTP credential passed the test but failed on real sends).

Migration

  • Adds 0013 (order justification: orders.justification + two asset_types flags) and 0014
    (asset_types.portal_step_visibility). Both additive (nullable / defaulted columns; no backfill).

ip·Solis v0.7.0

Choose a tag to compare

@github-actions github-actions released this 15 Jul 11:42

Added

  • Drift / out-of-band reconciliation (AD). A Beat task periodically re-reads the AD groups that
    drift_monitor asset types provision into and compares actual membership against what ip·Solis
    granted (from the order change log). Divergences — missing access (granted, removed in AD) and
    out-of-band (added directly, never granted) — are recorded to drift_findings, audit-logged
    (streamed to the SIEM), and surfaced on Operations → Drift. Opt-in per type; global schedule +
    detect_only / auto_remediate mode under Maintenance → Drift reconciliation; auto-remediate
    re-grants / revokes via AD. Best-effort email/Teams alert.
  • Software license & contract lifecycle. New SoftwareContract entity (vendor, product, value,
    billing interval, licensed seats, renewal date, notice period) bound 1 : N to asset types.
    The cost report prices each active order at the contract's per-seat rate (contract value ÷
    seats) instead of a flat monthly cost, and tracks utilization + unused-seat shelfware and
    seat over-allocation (Model A — actual consumption). New Reports → Licenses & Contracts
    page; daily opt-in renewal-reminder Beat task fires when a contract enters its notice window.
  • Slack approval delivery. Approvals can post a Block Kit message to Slack in parallel with
    email (and Teams), reusing the same channel-agnostic signed one-click approve link. Config
    slack.mode / slack.webhook_url + Settings section + test button; covers initial dispatch and
    reminders.
  • Signed attestation artifacts. Optional per asset type: a handover acknowledgment
    (Übergabeprotokoll) on provisioning — the recipient gets a signed link to confirm receipt (and an
    acceptable-use policy) — and a revocation / disposal certificate on revoke/expiry (audit
    evidence of what was removed). Signed-token HTML pages (archival via print); reviewed under
    Reports → Attestations; overdue-ack reminder Beat task.
  • Onboarding bundles & assignment rules. A Bundle groups existing asset definitions into a
    package; an AssignmentRule maps user attributes (department, cost center, …) to a bundle
    (reusing the approval-rule condition format). Ordering a bundle creates one lightweight
    OrderGroup with one order per position through the normal approval/execution paths (idempotent —
    asset types the user already holds are skipped). Triggerable from Onboarding admin (evaluate
    for a user), the self-service Packages catalog, a SCIM joiner, and optionally a user's first
    portal login (onboarding.eval_on_first_login).
  • SCIM joiner/mover provisioning. Extends the SCIM endpoint from leaver-only to full
    joiner/mover/leaver: a new ScimIdentity last-seen projection; POST/PUT /Users (opt-in
    scim.joiner_enabled) evaluate assignment rules and order matched bundles; a mover (attribute
    change) reconciles entitlements via scim.mover_mode (disabled / additions_only /
    reconcile), where reconcile also revokes lost entitlements — strictly limited to
    rule/SCIM-provisioned orders (self-service and manual orders are never auto-revoked).
  • Entra group provisioning (Microsoft Graph). The entra_group access-target type now grants /
    revokes Entra (cloud-only) security-group membership via Microsoft Graph (app-only, dedicated
    graph.* app registration). Closes the gap between Entra login (OIDC) and provisioning Entra
    groups for M365 / cloud-only customers. Settings card + Test Credentials.

Changed

  • Portal accessibility (structural). Skip link, main landmark + labels, decorative-icon
    aria-hidden, live notification badges, an early lang binding, and keyboard :focus-visible
    outlines across the shared portal templates — no visual redesign. Closes the BITV / EN 301 549
    structural basics (portal only; not a formal conformance claim).
  • SCIM full filter grammar (RFC 7644 §3.4.2.2). GET /Users?filter= now supports the full
    grammar (eq ne co sw ew gt ge lt le pr, and / or / not, grouping) instead of only
    userName eq; a malformed filter returns 400 invalidFilter. Added a read-only /Groups
    shim (empty list; group membership lives in AD, not SCIM).
  • Access-target validation. Saving an asset type now rejects access-target types without a
    provisioning handler (only ad_group / entra_group; rds_collection / other → 400).

Migration

  • Adds 00040012: drift findings + per-type flag; software contracts + asset_types.contract_id;
    Slack config; attestation artifacts + flags; onboarding bundles / assignment rules / lightweight
    order_groups + nullable orders.order_group_id; SCIM identity projection; SCIM mover config;
    Graph (graph.*) config; onboarding first-login config. All additive (new tables + nullable
    columns + seeded config); no backfill of existing rows.

Fixed

  • Feature-alert emails now send from the configured email.from address instead of the
    container's MAIL_FROM default, so drift / contract-renewal / attestation alerts match the
    rest of the platform's outgoing mail identity.

Testing

  • Autonomous feature-test harness (tests/feature/). A self-contained integration suite
    (58 tests) drives the running stack end-to-end over HTTP + DB and a testlab mock-receiver:
    order lifecycle (provision / modify / revoke / all deprovision policies, capacity, scheduled,
    ServiceNow-webhook HMAC), access provisioning against real AD and mock Microsoft Graph,
    drift detection, approvals + certification (incl. auto-revoke), HR leaver, SCIM JML, onboarding
    bundles, software-contract cost math + renewal, attestation emission/ack, cost & point-in-time
    access reports, LDAP portal login, real Teams delivery, and every Beat cycle. Namespaced and
    self-cleaning; not shipped in the runtime image.

ip·Solis v0.6.15

Choose a tag to compare

@github-actions github-actions released this 30 Jun 21:45

Changed

  • Licensing terms & texts updated for the free-tier / volume-band model (reviewed and approved). The XenPool Commercial Source License (LICENSE, EN + DE), the German AGB and the English Terms, plus the README and deployment/onboarding docs now reflect the sales model enforced since 0.6.14: free productive use for up to 25 active users (including in an organizational context), with commercial use (more than 25 active users) licensed in volume bands by active-user count. Adds an authoritative active user definition; the license scope wording changed from "licensed instances" to "licensed number of users / volume band (max. Active Users; 0 = unlimited)"; after expiry + the 30-day grace the software reverts to the Free Tier (no longer described as "evaluation only").
  • In-app license texts & shop links. The dashboard unlicensed-state banner is now a "Free tier · up to 25 active users" banner; the Maintenance license card explains the tiers and bands. All purchase / renewal calls-to-action now point to the ip·Solis license shop (locale-aware: …/en/shop / …/de/shop) instead of a sales email; sales@xenpool.de is retained only for inquiries, support and the imprint.

ip·Solis v0.6.14

Choose a tag to compare

@github-actions github-actions released this 30 Jun 19:55

Added

  • Free-tier / commercial-band user-count enforcement. A free productive tier allows up to 25 active end-users without a license; a valid commercial license raises the limit to its signed max_users band (e.g. 75 / 250; 0 = unlimited). "Active user" = a distinct (case-insensitive) orders.user_email on an order in an active status. Enforcement is soft: existing operation is untouched — only the creation of an order for a new (not-yet-counted) identity is blocked once at/over the limit (HTTP 403 across the portal, /orders API and the ServiceNow webhook). The Admin Dashboard shows a banner (red at the limit, amber from 80 %). The band rides on the existing 30-day license-expiry grace; demo/evaluation licenses never raise the limit. New endpoint GET /admin/tier/status.
  • Evaluation-license recognition & display. Demo/evaluation licenses (signed by the demo key) are now labelled as such: a dashboard "Evaluation license" banner and an "Evaluation" badge on the Admin → Maintenance → License card, with licensee and validity.
  • Built-in tile-icon picker for asset definitions. A bundled set of monochrome IT icons (Desktop/VDI, Laptop, Server, VM, Database, Mailbox, Application, License, Smartphone, Monitor, Cloud, Storage) selectable directly in the asset-type form — no upload needed. Stored as a data-URL like an uploaded logo, so the portal catalog renders them unchanged.
  • Reassign an asset definition while Free. Operators can change a personal asset's Asset Definition inline in Personal Assets, but only while the asset's status is Free (UI dropdown + server-side guard; rejected with 409 otherwise).

Changed

  • Unimplemented Access Target types marked "coming soon". In the asset-type form, Entra Group, RDS Collection and Other are now disabled and labelled "(coming soon)" — only AD Group is implemented end-to-end (the others were selectable but failed silently at provision time). Backend status documented in TASKS.md.
  • Admin Settings — OIDC provider field labels. Provider-ID placeholder aligned with the Entra example, and a help line added under Client ID.
  • Integrations docs — SMTP authentication options. New section (EN + DE) clarifying that ip·Solis is provider-agnostic SMTP-only (no vendor send APIs), with a decision table (relay vs. app password) and an M365 caveat recommending a relay for a future-proof setup.

Fixed

  • HTTPS OIDC redirect URIs behind the reverse proxy. uvicorn now runs with --proxy-headers --forwarded-allow-ips=* so it honours nginx's X-Forwarded-Proto; previously the app derived http:// callback URLs, breaking SSO with AADSTS50011. Image build/push/cache and tags are unchanged.
  • Admin status banners in dark mode. On reset, the dark: red/blue colour classes were not cleared, so a successful test (AD/SCCM/email/compliance) could render red. Banners now reset to base classes before applying the new state.

Internal

  • test_asset_type_constraints.py realigned with the migration-0047 validator (two create-time rules; runbook-wiring is now a dispatch-time concern) — the suite previously targeted the removed 5-rule API.

ip·Solis v0.6.13

Choose a tag to compare

@github-actions github-actions released this 28 Jun 14:23

Added

  • Admin Users — masked password reset. The "Reset password" action now opens a dedicated modal with a masked input and a show/hide (👁) toggle, replacing the native browser prompt() that always displayed the new password in cleartext. The same show/hide toggle was added to the Create-user password field for consistency.

Changed

  • Production overlay renamed: docker-compose.prelive.ymldocker-compose.prod.yml to match its actual role (the TLS/nginx production overlay; the old prelive name was historical and misled operators). All references updated — CI (deploy-prelive.yml), docker-compose.ghcr.yml usage comments, tools/install/bootstrap-certs.sh, README.md, and docs/DEPLOYMENT.md/.de.md (the COMPOSE_FILE examples now use docker-compose.prod.yml and the interim "historical name" clarifying comments are removed). The prelive environment and its deploy workflow keep their names — only the overlay file was renamed. Operator action: hosts that pin the overlay via COMPOSE_FILE (e.g. LinPre1/LinPre3) must update the filename; there is no back-compat alias.
  • Deployment guide clarified for first-time installers. The TLS section now states explicitly that certificate Options A/B/C are mutually exclusive alternatives, with an "end of options" callout before Configure nginx (the shared step). The Start the Stack intro was simplified — dropped the locales//scripts/ baked-in internals and version wording that confused first-time installers, keeping only pull/start and the prod-pin-vs-latest choice. (EN + DE)

Fixed

  • CI: stop uploading buildx .dockerbuild build records. The release workflow now sets DOCKER_BUILD_RECORD_UPLOAD=false (and DOCKER_BUILD_SUMMARY=false) at job level so the API and Worker build-push steps no longer emit the .dockerbuild artifacts that were accumulating on every release. Image build, push, cache, and tags are unchanged.

ip·Solis v0.6.12

Choose a tag to compare

@github-actions github-actions released this 23 Jun 22:33

Changed

  • Aligned and clarified the license wording across the documentation, the bundled LICENSE copies, and the Admin UI so they are consistent with the Terms.

ip·Solis v0.6.11

Choose a tag to compare

@github-actions github-actions released this 23 Jun 06:42

Changed

  • Deployment guide is now prebuilt-image (GHCR) only. docs/DEPLOYMENT.md documents a single supported install path — pulling the public ghcr.io/xenpool/ipsolis-{api,worker} images — and drops the build-from-source variant throughout (start, update, HA, troubleshooting, clean reset). The image tag now defaults to :latest, with per-environment guidance: pin IPSOLIS_VERSION in production, track :latest in pre-live / test.
  • License module docstring clarified. max_users / max_asset_types are parsed for display only and are not enforced at runtime (no feature/usage gating — all features ship in every edition). Corrected the misleading "enforces …" wording in api/app/utils/license.py and the byte-identical worker copy.

Fixed

  • License documentation corrected. The README's License section incorrectly claimed AGPL-3.0 / a "dual-licensed open core". ip·Solis is in fact source-available under the XenPool Commercial Source License v1.0 (free for non-commercial use + 30-day evaluation; commercial use requires a purchased license). Removed all AGPL references and aligned "open-source" wording to "source-available".
  • Deployment guide: sudo chmod +x for the mkcert binary (it is downloaded as root via sudo curl, so the non-sudo chmod failed with "Operation not permitted"); replaced the misleading acme.com example hostname with example.com.

ip·Solis v0.6.10

Choose a tag to compare

@github-actions github-actions released this 22 Jun 09:08

Added

  • Provider-agnostic portal SSO (generic OIDC). The self-service portal now authenticates users against any standards-compliant OpenID Connect identity provider — Entra ID, Okta, Ping, Google, Keycloak, Authentik, Zitadel, … — through a single code path. Each provider self-configures from its issuer URL via the discovery document (<issuer>/.well-known/openid-configuration); adding an IdP is a config entry, not a vendor integration. New helper api/app/utils/oidc.py validates ID-token signatures against the provider JWKS (PyJWT) plus iss/aud/exp and the OIDC nonce.
  • OIDC provider registry. Providers are stored in app_config under idp.<id>.* (unlimited providers, stable URL-safe ids). Admin → Settings → Authentication gains an add/edit/delete provider UI with a Test button that runs a discovery probe. New endpoints: GET /admin/config/oidc/providers, PUT/DELETE /admin/config/oidc/{provider_id}, POST /admin/config/oidc/{provider_id}/test, PUT /admin/portal-auth.
  • Login method picker. When more than one login method is enabled the portal shows a chooser at /portal/login (fully localised, 5 locales); with exactly one it redirects straight to it.
  • On-prem LDAP portal login. Username/password login against on-prem AD/LDAP, offered alongside OIDC via auth.ldap_enabled (folds in the earlier short-lived onprem_ldap mode).
  • Reuse existing tile logos. The asset-definition form gains a "Choose existing" logo picker that reuses any logo already attached to another asset type (deduped), no re-upload. New endpoint GET /admin/asset-type-logos.
  • Prebuilt-image install (GHCR). New docker-compose.ghcr.yml pulls the public ghcr.io/xenpool/ipsolis-{api,worker} images instead of building — faster, version-pinned installs (IPSOLIS_VERSION). locales/ and scripts/ are now baked into the images (root build context + .dockerignore) so a prebuilt install needs no repo checkout of them.

Changed

  • Parametric OIDC callback. Portal callback is now /portal/auth/{provider_id}/callback (was the Entra-only /portal/auth/callback). Logout is generic RP-initiated logout via each provider's end_session_endpoint.
  • Portal auth gate. Replaced the Entra-specific entra.mode with portal.auth_required (login on/off) + per-provider idp.<id>.enabled + auth.ldap_enabled. Migration 0003 seeds the toggles and migrates any existing entra.* config into idp.entra.*. Service-health probe entra renamed to sso (probes discovery for every enabled provider). SAML 2.0 remains out of scope (separate task).
  • Admin sidebar layout. Audit Log and API Tokens moved into the compact footer section; theme toggle + signed-in user moved to a sticky top-right header — frees vertical space so the nav no longer needs an internal scrollbar.
  • Script modules are PowerShell-only. The Script-type dropdown is removed (Python/Bash were never functional — the worker injects a PowerShell-only $VARS/$PARAMS preamble); the API coerces script_type to powershell. Module + runbook editors are now English-only.

Fixed

  • Login-settings save returned 422. PUT /admin/config/portal-auth was shadowed by the generic /config/{key} route (parsed as a config key, rejected the body as missing value). Moved to PUT /admin/portal-auth.
  • Portal i18n on prelive. Locales are now baked into the api image, so prelive's volumes: [] ("baked code") no longer leaves /app/locales empty (i18n had silently fallen back to English).
  • nginx config + SSL paths. Mount nginx.conf to conf.d/default.conf (not the main nginx.conf); unified the SSL cert path to nginx/ssl/ across all compose files and docs.
  • Docs: corrected all "alembic upgrade head is automatic" references (it is not); wrapped long docker compose commands; added the first-install alembic step + an SSL pre-flight to the update section.

Removed

  • Entra-only MSAL login path. api/app/utils/entra.py and the entra.* config keys are retired; the generic OIDC path supersedes them (no MSAL-only feature was in use). msal is retained only for the legacy Entra credential test.
  • entra_with_onprem auth mode. Removed entirely (never fully implemented; no production deployments).

CI / Build

  • Build images from the repo-root context so shared locales/+scripts/ can be baked; added .dockerignore to keep secrets (.env, licenses/, backups/, nginx/ssl) and .git out of the images.
  • GHCR packages made public (anonymous pull); actions/checkout v4 → v5 (Node 20 deprecation).

ip·Solis v0.6.9

Choose a tag to compare

@github-actions github-actions released this 13 Jun 23:18

Added

  • Update Notifier: "Check now" button. Triggers an immediate update check from the Settings page without waiting for the daily Beat tick. Shows inline feedback: "Up to date", "New version available: vX.Y.Z", or the actual error text — auto-fades after 5 s on success.
  • Update Notifier: GitHub Release created on tag push. release.yml now includes a create-release job that extracts the matching CHANGELOG section and publishes a GitHub Release after images are pushed. Previously only a git tag was pushed, causing releases/latest to return 404.

Fixed

  • Update Notifier: 404 no longer shown as error. When the GitHub repo has no published releases yet, the checker now clears the error field and logs "no releases yet" instead of recording a failure.
  • Update Notifier: error box shows actual error text. Settings page previously displayed the static "See server logs for details" message regardless of the real error. Now shows the stored updates.check_error value.

ip·Solis v0.6.8

Choose a tag to compare

@XenPool XenPool released this 13 Jun 23:03

Added

  • Portal nav badges. My Approvals, Delegations, and Access Reviews now show a live count badge (red / amber) when the signed-in user has pending items. Loaded via GET /portal/nav-badges (3 parallel COUNT queries) on every page without touching existing route handlers.
  • Retry failed orders. Admin order detail shows an amber "Retry now" button when an order is in failed state. Clears the step history, resets the order to processing, re-dispatches the runbook, and writes an audit row.

Fixed

  • Audit log: admin cancel now records the acting user. POST /ui/orders/{id}/cancel was missing request: Request, so the audit triggered_by showed celery:dynamic_runner instead of the admin session. Fixed.

Changed

  • Admin order detail: Admin Actions moved above Execution Steps. Cancel / Extend / Retry panel now appears directly below the user and asset cards, before the step log.
  • Docs: ServiceNow webhook fully documented. integrations.md section rewritten from a 4-line stub to a complete integration reference: both auth methods, full payload schema, curl example, complete response JSON, capacity checks, idempotency, error table, and audit trail. Fixed incorrect scope name webhook:servicenowwebhook:in.