Changelog
From CHANGELOG.md in the repository.
Every release of Softwarden, newest first. The format follows Keep a Changelog and versions follow Semantic Versioning.
[1.0.0] - unreleased (set on tag day)
The first release of Softwarden: an open-source system of record for the software, SaaS, integrations and AI agents an IT team runs. Install it on one Linux VM with Docker Compose (docs/INSTALL.md, then docs/FIRST_RUN.md for discovery), or on Kubernetes with the Helm chart. Features marked (enterprise) need an enterprise-edition organization; everything else is in the community edition. An operator makes an organization enterprise with manage.py set_edition <org-slug> enterprise (audited); there is no license check yet (docs/CAPABILITIES.md, “Setting the edition”).
Two kinds of feature are marked as well. (API only) means there are no screens yet: use the REST API. (preview) means the feature is hidden unless the installation sets SOFTWARDEN_PREVIEW_FEATURES=1 (docs/CAPABILITIES.md, “Preview features”). Preview features were built and tested against simulators and the vendors’ documentation only, never against a live Okta, Google Workspace, ServiceNow or Halo tenant, so treat them as untested in production. With the setting off, auth/me leaves out the preview, discovery.okta and discovery.google capabilities, their routes answer 403, the discovery and ticket schedules skip them and the app doesn’t offer them. Stored data is kept and used again once the setting is on.
Added
Catalog and relationships
- Applications, components (scripts, APIs, services, workflows, automations), integrations and AI agents, each with owners, a support team, an IT steward, lifecycle, environment, hosting, data classification, URLs and the Entra, Azure and Power Platform IDs that tie them to what discovery finds.
- AI agents with their platform, channels, models and providers, data access scope, human-in-the-loop decision and whether their actions can write; a models-in-use report.
- People, teams, departments, vendors (with support contacts and an account manager), tags and categories.
- Custom fields defined by Admins, on records and vendors, with validation, list filters, exports and import.
- Attachments (files and links) on records, vendors and contracts, with size limits and content checks.
- Relationships (depends on, implements, replaces, and your own types with inverse labels), integrations as data flows, link confirmations, a dependency explorer and a map per record, cycle-safe, with saved change assessments.
- Reviews with due dates, Needs attention queues for ownership gaps, overdue reviews, links to verify and AI agent gaps, data-quality rules with exceptions and a completeness score.
- Global search across records, vendors, people and attachments; a command palette and keyboard shortcuts.
- Lists with filters kept in the URL, chosen columns, saved views (personal or shared) and CSV and Excel export.
- CSV import with a template or your own column mapping, a preview with decisions on possible matches, and a commit that saves everything or nothing.
- Bulk edit of up to 200 records with a preview, and Admin bulk delete that names what blocks it.
- An audit log of every change with before and after values and diffs, a History tab on each record, and CSV export; JSON lines export for a SIEM (enterprise).
- Organizations with Admin, Editor and Viewer roles; one account can belong to several organizations.
- An optional compliance profile (GxP fields), off by default (enterprise).
- A vendor risk file per vendor: security questionnaire, assurance report (SOC 2, ISO 27001), DPA, subprocessors, risk tier and notes. Dated documents read as current, expiring or expired, and each expiry date is a reminder (the built-in “Vendor risk documents” rule: 60, 30 and 7 days before). A high or critical vendor with no current SOC 2 or equivalent, and a vendor processing personal data without a signed DPA, are Needs attention gaps. There is a risk overview and a documents list, each with a CSV.
- A data-flow map. Integrations record the kinds of data they carry (personal, special-category, financial, credentials, health, customer content, other). The map answers “where does confidential data go?” with filters, a graph and an audited CSV. It flags risky flows: confidential or personal data to a vendor with no DPA, no authentication to an external vendor, and flows classified above the record receiving them. Risky flows are a Needs attention queue, and two data-quality checks ask for an integration’s classification and categories.
- End-of-life tracking via endoflife.date. Map an application, component or instance to a product and release cycle and see each version’s status (supported, security fixes only, end of life), its end-of-life date and the days left. There is a calendar with filters and a CSV, and a Needs attention queue. The built-in “End of life” rule reminds 90, 30 and 7 days before, then every 30 days while a version is past its end of life. A daily worker job refreshes the public data (ETag-aware); for air-gapped installs, set
SOFTWARDEN_EOL_ENABLED=0and usemanage.py eol_import. - Offboarding and access review. A person’s page lists everywhere they appear: records, AI agents (including those running as them), integrations, IT stewardship, teams, vendors, contracts, renewals, reviews, assessments, data-quality exceptions, discovery and the Entra owners of discovered apps (and, for Admins, notification rules and their account), with a CSV. Reassign hands chosen roles to an active colleague in one transaction, one audited change per row, never deleting. The access review flags inactive owners, owners whose account was deactivated or removed, records with no owner and Entra owners that differ from the catalog’s, with a CSV.
- Catalog as code (
docs/CATALOG_AS_CODE.md): the catalog as one YAML file per record for a git repository, in a stable format that diffs well in pull requests. Export it, plan, and apply through the same services, limits and audit log as the app, in Administration or withmanage.py catalog_exportandcatalog_apply. A stale plan is refused; prune is opt-in. Admin only. - Ticket links on change assessments and renewals: paste a Jira, ServiceNow, Halo or other ticket address and the system and key are parsed; the status can be set by hand. With a Jira connection (an account email and API token, encrypted and write-only), the worker reads open tickets’ status hourly, and an Admin can allow creating a ticket from an assessment or renewal (off by default; every attempt audited). ServiceNow and Halo ticket connections are (preview); without the preview setting their pasted links still work with a status set by hand.
Contracts, licenses and spend
- Contracts with lines that split the cost across the applications they cover, amounts kept exactly (never rounded through floating point), billing frequency, annualized cost, notice period and the cancellation deadline it implies.
- Renewals with cycles and history, linked to one contract as their single source of dates, and a Renew action that starts the next term.
- License pools with seats purchased and assigned, utilization and over-use warnings, and a seat count review; seat counts can follow Entra license data.
- A dashboard, spend and deadline reports with CSV export, and an ICS calendar feed of renewal deadlines.
- Contract and license pool imports.
- License waste (API only; the screens come in a later release), from the discovery source
entra_licence_usage. It reads each licensed user’s licenses (User.Read.All) and last successful sign-in (AuditLog.Read.Allwith Entra ID P1).GET /api/v1/reports/licence-wasteshows, per SKU, assigned, active, new, inactive, never signed in, disabled and unknown licenses, guests and service accounts. It also shows the annual cost of reclaimable and unassigned seats from the contracts of the license pools bound to the SKU, with totals per currency and named gaps where no price is known. It has filters and an audited CSV, and an Admin-only per-SKU drill-down. License pools and contracts get license waste blocks, and the offboarding footprint lists a person’s licenses. The inactive threshold is an organization setting (inactive_seat_days, default 90). Without P1, licenses are still counted and the last sign-in is unknown. Only a keyed hash of each user’s object ID, SKU IDs, flags and dates are stored.
Reminders and notifications
- Reminders for renewals, cancellation deadlines, reviews and date custom fields, with snooze, acknowledge and resolve.
- Notification rules that decide who hears about what and when, with a preview and a test send; the daily digest is one of them.
- Delivery by email (Microsoft Graph sendMail or SMTP), Microsoft Teams (Workflows) and webhooks, with a delivery log and resend.
- Weekly emails of a saved view, and a profile switch to turn them off.
Discovery and the assistant
- Read-only discovery from Microsoft Entra: enterprise applications, app registrations, their owners, expiring secrets and certificates, licenses and agent identities.
- Read-only discovery from Azure, Power Platform and HaloITSM (enterprise).
- Shadow IT from Microsoft Entra ID: the source
entra_shadow_itreads the sign-in logs (AuditLog.Read.All, Entra ID P1 or P2) and OAuth consent grants (Directory.Read.All). Third-party apps nobody registered become discovery candidates, with users and sign-ins over 30 days, consent type and high-risk scopes. The Shadow IT page has filters and an audited CSV. Reads are incremental, and only daily counts and a HyperLogLog sketch of hashed user IDs are stored, never sign-in rows or user IDs. - SSO and MFA coverage gaps: the source
entra_coveragereads each linked Entra app’s single sign-on mode, SCIM provisioning jobs (Synchronization.Read.All) and conditional access policies (Policy.Read.All, Entra ID P1). The SSO coverage report has filters and an audited CSV, the application page shows the gaps, and the data-quality rules No SSO, No MFA policy and No SCIM use it. Without P1, MFA is unknown and the rest is still reported. Curated SSO and SCIM fields are never written; differences are shown. - Okta applications and Google Workspace third-party apps (from the OAuth token audit log) as discovery sources (enterprise) (preview).
- Connections with encrypted, write-only secrets, a connection test that names any missing permission, a guided setup per source, live run progress and run history. Every permission requested is listed in
docs/PERMISSIONS.md. - Discovery never overwrites what you curated: findings go to a reconciliation queue as suggestions to link, create or dismiss, with Undo; differences from the source, records no longer seen and items out of scope are shown for you to decide.
- An assistant that suggests links and new records from discovery findings, using Claude with your own API key and a monthly cost cap, with a usage log (enterprise).
API, webhooks and MCP
- A REST API at
/api/v1/for everything the web app does, with an OpenAPI schema and an in-app API reference, RFC 9457 problem details, keyset pagination, ETag and If-Match on edits, and rate limits per token and per user. - Composite endpoints for common questions (deadlines, renewals with owners, spend, dependencies, discovery summary, data gaps, expiring credentials).
- API tokens, read-only or read-write, shown once.
- Signed webhooks with event subscriptions, retries with backoff, an attempt log, ping, secret rotation and automatic disabling of failing endpoints, written through an outbox in the same transaction as the change.
- An MCP server (
ghcr.io/softwarden/softwarden-mcp) that lets an AI assistant read the catalog through the API with your token, with opt-in writes guarded by If-Match; stdio or token-gated HTTP behind Caddy.
Identity
- Local accounts with first-run setup, invitations with copy-once links, a pending-access list for auto-provisioned users, and an operator command to reset a locked-out Admin.
- Single sign-on with OpenID Connect per organization, with presets for Microsoft Entra ID, Okta and Google and a generic one, set up as a draft, tested, then activated, with a recovery runbook.
- SAML 2.0 single sign-on (enterprise).
- SCIM 2.0 provisioning of users and groups from Microsoft Entra, with per-organization tokens and optional roles from groups (enterprise).
Self-host operations
- Docker Compose install behind Caddy with automatic TLS (your certificate, Let’s Encrypt or Caddy’s local CA) and no settings file needed: secrets are generated on first start.
- A Helm chart for Kubernetes with an external PostgreSQL 17. With
secrets.existingSecretit setsSOFTWARDEN_CREDENTIAL_KEYS_FILEandSOFTWARDEN_BACKUP_KEY_FILEto the Secret’scredential_keysandbackup_key, which outrank keys given throughextraEnv;database.sslmodesetsPOSTGRES_SSLMODE, which also reaches the backup’spg_dump. The worker’s liveness probe isrun_worker --check --local, the pod’s own heartbeat. - Export all of an organization’s data as a zip, by its Admins, in every edition.
- Nightly encrypted backups of the database and attachment files from the worker, with retention, a disk-space floor,
backup_now,ops/restore.sh --rehearseand the last good backup’s age on the System page. - Forward-only migrations,
upgrade_checkwith a manifest of what must survive an upgrade, and an upgrade runbook; CI rehearses every upgrade by restoring a backup of the previous release under the new image. manage.py doctor, which checks the whole setup without printing secrets.- JSON logs with request ids and secret scrubbing,
/readyzfor monitors,/healthz/opsfor operators (it reports this version), and optional OpenTelemetry traces. - Security headers and a Content Security Policy in Caddy, rate limits on sign-in and the API, upload content sniffing, a dependency audit in CI, and
SECURITY.mdwith the security model and how to report a vulnerability. - Release images for the app and the MCP server on GitHub Container Registry, each with an SBOM and a signed provenance attestation.
- No outbound connection except to the services you configure: no CDN, telemetry or external fonts.
Hosted (cloud) edition
- A hosted deployment mode (
docs/CLOUD.md):SOFTWARDEN_DEPLOYMENT=cloud,POSTGRES_SSLMODEandPOSTGRES_SSLROOTCERT,doctor’s cloud checks, first-run setup that creates platform staff, and the Helm chart’svalues-cloud.yamlwith separately scaled workers, PodDisruptionBudgets and an optional HPA. - Public signup with email verification, off by default (
SOFTWARDEN_SIGNUP_ENABLED), which creates a cloud organization and its Admin; invitations by email. - An Admin of a cloud organization can delete it after an export and a grace period (30 days by default, cancelable until then).
- Per-organization limits (records, connectors, members, attachment storage, API rate), generous by default in cloud and unlimited in community and enterprise, and a nightly backup of each cloud and enterprise organization’s data that its Admins can download.
- A platform console for whoever runs the service: every organization with its usage, edition changes, suspension, per-organization capability overrides and limits, and impersonating a member, with re-authentication, a reason, a time limit and a banner. Every platform action is audited.
Security
- Simulated tenants and hosts are refused outside development: the Microsoft tenant
simulatedand the*.simulated.invalidhosts (Halo, Okta, Google, Jira, ServiceNow, Graph email) work only withSOFTWARDEN_DEBUGon, in the Playwright server, or with the newSOFTWARDEN_ALLOW_SIMULATED=1. Otherwise they are refused on save, at the connection test and when a run, ticket refresh or email starts; existing ones are kept but don’t run, anddoctorwarns.seed_demorefuses without the flag, so the Docker demo sets it in.env(README); the dev stack sets it. The sign-in simulators are unchanged (DEBUG or Playwright only).
Known limitations
- License waste has no screens yet (API only, above), and a contract line covering several SKUs can’t be priced per SKU yet.
- Preview features (Okta and Google Workspace discovery, ServiceNow and Halo ticket connections) are hidden by default and have not been tested against live tenants.
- End of life: the overview has no criticality or owner filter in the API (the app filters on screen), and an instance’s version can’t be edited in the app yet.
- Audit events are kept forever; configurable retention isn’t built.
- The hosted edition has no billing and no transactional email provider yet; it sends email through the installation’s SMTP or Microsoft Graph settings.
- Imports of more than 500 rows run inside the request rather than as a background job; about 5,000 rows is the practical limit before the 120-second request timeout.
- Webhook deliveries are queued in one order across all organizations, so one organization that produces a flood of events delays the others’ deliveries.
- The web app’s router (react-router 6) has moderate security advisories that need the migration to react-router 7; none is rated high.
- Release images are built for linux/amd64 only; on arm64, build from source.
- SCIM was tested against a replay of the Microsoft SCIM Validator’s request sequences, not the hosted validator itself.