Changelog
Every release, newest first. The version you are running is shown at the bottom of the app's Settings page.
v0.8.2
08/08/2026- SAML documents are now parsed with entity resolution, DTD loading, and network access all switched off, and any document carrying a `<!DOCTYPE>` is refused outright. A SAML response arrives at the assertion consumer endpoint before anyone has proved who they are, and its status is read before its signature is checked, so that parse was reachable by anybody who could reach the endpoint. A crafted document could have been used to read files off the TFsmith host or to make it fetch a URL of the sender's choosing. No standards-compliant identity provider sends a DOCTYPE, so this changes nothing about normal sign-in.
- Fetching identity provider metadata by URL is now restricted to http and https, follows at most three redirects, and refuses a document larger than 2 MB. Local addresses are unaffected - metadata hosted on your own network, including a self-hosted authentik, works exactly as before.
- The authorization endpoint advertised in an OpenID Connect discovery document must now live on the same host as the issuer and cannot downgrade an https issuer to http. A tampered or hostile discovery document can no longer bounce a sign-in attempt to an unrelated site.
v0.8.1
08/08/2026- The create-user form is behind **+ Add user** again. It was rendering inline and always open, so the Users section looked like a form rather than a list.
- With single sign-on configured, a user created by hand is now **external** automatically - the checkbox is ticked and locked, with the reason shown. Once SSO is on, staff accounts arrive from your identity provider at first sign-in or over SCIM, so anyone still being typed in here is by definition someone outside your directory. Role and password are unchanged: external users sign in with a password, so they still need both. Enforced server-side, not just in the form.
- Creating or inviting a user now takes first and last name.
- **Save security settings** confirms it saved. It had no success feedback at all, so a successful save was indistinguishable from a dead button. Saving SSO settings and toggling SCIM now confirm too.
- Email addresses are checked for uniqueness when creating or inviting a user, not only when editing one.
v0.8.0
08/08/2026- Single sign-on, **Business plan only**. Sign in with your identity provider over OpenID Connect or SAML 2.0, configured in Settings > Single sign-on. For OIDC, point it at your provider's issuer URL and it reads the rest from the discovery document. For SAML, paste the IdP metadata URL and it reads the entity ID, sign-in endpoint and signing certificate from it. A Test connection button checks the provider before you turn anything on. The Individual plan is a single-user plan, so SSO is part of what Business buys.
- SCIM 2.0 provisioning. Your identity provider can create, update and deactivate TFsmith accounts automatically. Deactivating someone in your directory disables their account here - it is never deleted, so the audit trail survives.
- Push Groups. Groups your provider pushes over SCIM appear in their own section and each can be mapped to a role. Someone gets the highest role they are mapped to across their groups, re-evaluated whenever membership changes.
- SSO mode **Required** turns password sign-in off, and break-glass accounts. Flag an administrator as break-glass and that account keeps password sign-in when SSO is required - the way back in if your provider is down. You can flag your own account, which on a single-admin install is the only way to set one up. Break-glass sign-ins are called out separately in the audit log.
- Accounts can be marked **external** - contractors and client engineers who are not in your directory. They keep password sign-in when SSO is required, and directory group mapping leaves their role alone.
- People can now sign in with their email address, and accounts carry first and last names shown as "First Last (email)" throughout.
- **Public URL** setting, under Settings > Security. SSO builds its redirect URI and SAML endpoints from it, so it is set before configuring SSO.
- **Edit** on any user row, matching IdPVault. One dialog for first and last name, email, role, and the external and break-glass flags, instead of a row of single-purpose buttons. Your own row is editable - on a single-admin install that is the only way to flag the first break-glass account - though you still cannot change your own role.
- **Reset MFA** for someone who has lost their authenticator. It appears only on accounts that actually have two-factor enabled.
- The users table now shows the display name, email, role, MFA and status, with break-glass, SSO and external called out as badges.
- Accounts created before this release keep signing in with their username exactly as before. Nothing needs changing on an existing install.
- Your identity provider owns the names of anyone who signs in through it - they refresh at every sign-in.
- SSO cannot be set to **Required** until at least one active administrator is flagged break-glass and has MFA enabled. Once required, that pairing cannot be taken away: disabling, deleting, demoting, or clearing break-glass on the last such account is refused, and your directory cannot deactivate it over SCIM either.
- Group role mapping never changes a break-glass account, never changes an external user, and never demotes the last active administrator. Every skipped change is recorded in the audit log with its reason.
- Accounts created by your identity provider cannot sign in with a password at all, in any mode.
- SAML responses must be signed, are matched to the request that started them, and are read only from the signature-verified part of the document.
- Email addresses are unique across accounts, compared case-insensitively.
- Resetting MFA on the last break-glass admin is refused while SSO is required - that account's MFA is half of the way back in.
v0.7.6 - 0.7.8
07/29/2026- Settings sections are collapsible. Tenants, Users, Security, Email, License and Audit log all start closed, so the page opens as a short index instead of a long scroll. The chip beside each heading shows what is inside without opening it: tenant and user counts, whether email is configured, and your license tier.
- A disabled user can now be deleted. Delete appears only once an account is disabled and asks you to type the username to confirm. It removes the account along with its sessions and any pending invite or password-reset link, so an emailed link can never outlive the account it was issued for.
- The audit log keeps the person's name after the account is gone, so history stays readable.
- Tenants can be edited after they are connected: Settings > Tenants > Edit... renames a tenant, corrects its base URL, or rotates its API token. Removing and re-adding a tenant is no longer the only way to change a credential.
- Leaving the credential fields blank keeps the current token, and the stored token is never shown. Changing the URL or the token revalidates against the provider before saving, so a typo cannot leave a tenant that no longer authenticates.
- A rename keeps everything already pulled: the tenant's internal identifier does not change with its name. The provider itself still cannot be changed - connect a new tenant for a different one.
- A resource type your tenant will not let TFsmith read no longer fails the whole refresh. Previously a single unreadable endpoint meant no data at all came back; now every other resource type is pulled normally and the one that was refused is listed as "not available" with the reason from your provider. This affects, for example, Okta orgs without API Access Management, which return an error for authorization servers.
- The reason is shown on the resource type itself, so a type that could not be read is never mistaken for one your tenant simply has none of. Unavailable types are excluded from bundle exports.
- Errors from a provider now include that provider's own error code rather than only an HTTP status.
v0.7.5
07/25/2026- The plan's tenant limit is now enforced, not just displayed. Tenants past the limit are locked rather than deleted: the oldest tenants stay active in the order you connected them, and browse, Refresh, and Terraform export are all blocked for a locked tenant. Nothing is removed, so adding a tenant add-on or removing another tenant unlocks it again.
- The Add tenant button is now disabled, with the reason on hover, once you are at your plan's tenant limit. It previously opened the form and only failed after you filled it in and clicked Connect.
- Settings > Tenants gained a Status column showing which tenants are active and which are locked.
v0.7.0 - 0.7.4
07/24/2026- Read-only architecture hardened: the provider adapters now expose exactly two operations, credential validation and export. The unused restore, clone, and identity write code (TFsmith is export-only) was removed, so there is no longer any code path that can write to a connected tenant.
- The first-run License screen now notes that activating a license accepts the Terms of Service at tfsmith.com/terms.
- Added a LICENSE file (End User License Agreement); canonical terms remain at tfsmith.com/terms.
- Auth0's auto-created global client ("All Applications" - it carries the tenant-wide classic login page config, it is not a real application) is now skipped in Terraform export with an honest reason, like Okta's system apps.
- Auth0 types now use the DASHBOARD's names: Applications (was Clients), APIs (was Resource Servers).
- New Auth0 type: Application Grants (the M2M application-to-API authorizations) - exported as auth0_client_grant with import blocks; the application reference rewrites to a Terraform expression when the application is in the same bundle. Click Refresh on an existing Auth0 tenant to pull them.
- Auth0 connect fixed: the form now asks for the M2M application's Client ID and Client Secret (the adapter mints its own short-lived Management API tokens from them) instead of a single token field that never matched how Auth0 authenticates. Okta and Authentik keep the token field; the Base URL placeholder now follows the selected provider.
- In-app documentation: seven topics (getting started, connecting a tenant, the refresh model, Terraform export, licensing, users/roles/MFA, deployment and backups) under the Docs button, with a topic sidebar. The same docs publish to tfsmith.com/docs.
v0.1.0 - 0.6.4
07/23/2026- Settings and Profile readability: sections are clearly separated with dividers and breathing room, and the panel is wider.
- Connect now shows what it is doing: the button disables, a spinner appears, and a note explains the first pull can take a minute on a large tenant. Double-clicking Connect no longer creates the tenant twice.
- Email addresses are now settable after account creation: your own in Profile, anyone's via Set email in Settings > Users. (First-run setup never asked for one, so reset links and expiry warnings had no address to go to.)
- Tenants section in Settings: remove a tenant (typed-name confirm; deletes the stored export; never touches the provider). The backend route existed since 0.3.0 - the button did not.
- Roles: admin and user. Users browse, export, and Refresh, and manage their own profile; admins get Settings, user management, license, and tenant add/remove. Role picker on create/invite, role change per user, and the last active administrator can never be demoted or disabled.
- Email (SMTP) settings: your own mail server, password encrypted at rest, test-send button. TFsmith never sends anything anywhere else.
- User invites: create an account by emailing a set-your-password link (expires in 72 hours).
- Forgot password: reset links from the sign-in screen (2-hour links, no account enumeration). Admin reset in Settings still works without email.
- License expiry warnings: admins with an email on file get a heads-up at 14/7/3/1 days before expiry; renewals reset the schedule.
- Users and admin: create users (within the license cap - Individual is a single user, Business is unlimited), disable/enable, admin password reset. The last active account can never be disabled.
- Profile for every user: change password, enroll TOTP MFA with an inline QR code (secret stored encrypted with the master key), disable with a current code. Login is MFA-aware.
- Security settings: require-MFA toggle (unenrolled users are sent to Profile to enroll on next load) and session length (1-365 days).
- Audit log viewer in Settings: who did what, when (viewer-local time).
- Settings gear moved into the sidebar footer next to the theme toggle.
- The refresh model: the provider is pulled automatically exactly once, when a tenant is added. After that only the Refresh button pulls - page loads never touch the provider API. The export is persisted to the data volume encrypted with the tenant's data key, so it survives restarts and every user of the install shares the last refresh (ten users cost the same API calls as one).
- "Last refreshed Today, 7/23/2026, 9:41 PM" next to the Refresh button (viewer-local time; Yesterday and bare-date forms; an amber note past a week: "Over a week since the last refresh - the tenant may have changed.").
- Tenants connected before this version show "No data pulled yet" - one Refresh click and they are current.
- Phase 2: the product works end to end. Connect a tenant with a READ-ONLY admin API token (validated against the provider before storing; envelope encrypted at rest exactly like IdPVault). Browse resource types with live counts and type badges (OIDC/SAML/SWA...), click any object for its Terraform block + import block (Copy / Download .tf, with the full note set), or export a bundle zip (per-type .tf, provider.tf, variables.tf, import.tf, coverage README). Live provider fetch with a short in-memory cache; plaintext config never touches the database.
- Daily license check-in (2:15 UTC) plus a boot refresh - renewals and added tenants now apply automatically, closing the Phase 1 gap.
- Tenant cap enforced from the signed license payload (2 included, add more at tfsmith.com/manage).
- Provider adapters lifted from IdPVault v1.3.0 (okta/auth0/authentik export paths + adaptive rate limiting).
- Phase 1: first-run admin wizard, scrypt + DB-session sign-in, and the LICENSE GATE - no free tier; without a valid license only the License screen is reachable, with a purchase link to tfsmith.com, the install id, and an offline license file upload. TFSM activation keys activate against license.keltech.ai (only the key and install id are ever sent); offline entitlement files verify with zero network calls. Deactivate releases the license for another install. Headless bootstrap via TFSMITH_ADMIN_USER / TFSMITH_ADMIN_PASSWORD.
- Phase 0 skeleton: FastAPI app boots against Postgres, owns its schema (settings, users, session_tokens, tenants, audit_log), serves /healthz.
- Terraform engine, provider schemas, crypto, license verification, and activation client lifted from IdPVault v1.3.0 (TFSM key prefix, TFsmith User-Agent). Not yet wired to routes.
- Docker image + entrypoint (first-boot key generation, PUID/PGID, drops root), CI (tests gate every build; :dev from dev, :latest from main).