Skip to content

Releases: itambox-community/itambox-webapp

ITAMBOX v1.0.0-beta.6

ITAMBOX v1.0.0-beta.6 Pre-release
Pre-release

Choose a tag to compare

@itambox itambox released this 22 Oct 01:07
Immutable release. Only release title and notes can be modified.
7b90480

Security

  • Raised pypdf to 6.21.2 and virtualenv to 21.14.12 for advisories the vulnerability database published after v1.0.0-beta.5: four MEDIUM findings in the PDF library, which ships in the release image, and two HIGH findings in the virtualenv development tooling. Both stay inside the ranges pyproject.toml already declares, and the dependency security gate that had started failing on every pull request passes again.

ITAMbox v1.0.0-beta.5

ITAMbox v1.0.0-beta.5 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 21 Oct 19:33
Immutable release. Only release title and notes can be modified.
33129bf

Compatibility

  • Breaking for upgrades: the prerelease migration history is replaced by a named 1.0 baseline. Each app now ships 0001_baseline followed by 0002_cross_app_relations where relations cross apps, and the seed and database-guard migrations (assets.0004_seed_reference_data, 0005_core_vocabulary, 0006_core_vocabulary_german_translations, 0007_asset_type_identity_guard, extras.0003_definition_guards). The issue88_shard_*, issue-numbered and auto-named migrations are gone, and a fresh install no longer runs the prerelease data conversions. Every baseline migration declares the prerelease identities it replaces, so a v1.0.0-beta.5 database records the baseline without executing it and then applies only two idempotent clean-ups (extras.0004_drop_legacy_column_default, users.0002_unique_constraint_names). A fresh install and an upgraded database end in the same schema and the same migration-recorder state. The supported upgrade origin is v1.0.0-beta.5; a database from v1.0.0-beta.4 or earlier must first be upgraded to beta.5, and migration_baseline_preflight rejects it. A plugin migration that names a first-party migration in its dependencies must be updated to the new names.

Added

  • Plugins can declare host-mounted REST resources using the Stable core model viewset bases and declare plugin-owned permission targets through PluginConfig.permission_targets. The host owns authentication, permission and schema defaults, rejects viewset overrides that bypass host authentication, permission checks or scoped list/detail handling, applies core tenant-scope rules after plugin queryset overrides and filter-backend processing, and includes declared targets in SSO role policy, Technician seed permissions and the tenant role matrix. Plugin GraphQL is query-only; writes use the host-owned REST surface.

Changed

  • Breaking: The bundled Compose db service now runs PostgreSQL 18, and its named volume is mounted at /var/lib/postgresql instead of /var/lib/postgresql/data because the 18 image keeps its cluster in /var/lib/postgresql/18/docker. An existing 16 data directory is not readable by the 18 image: replacing the image on a running stack starts an empty cluster beside the old files, so an existing installation has to move its data with a dump and restore or pg_upgrade before it switches. PostgreSQL 16 remains a tested compatibility version; 15 and older are no longer tested. Follow the major-version database upgrade procedure.
  • The requestedScope argument of the GraphQL assets and asset queries is now optional and defaults to the scope of the current session; an explicit selector still overrides it and invalid selectors still fail with INVALID_SCOPE.
  • GraphQL list and detail queries for accessories, consumables, kits, components and licenses now follow the session scope, so a tenant-group or all-accessible session returns the same objects as the REST API instead of only tenantless rows.
  • Plugins are configured through ITAMBOX_PLUGINS_CONFIG (JSON keyed by plugin package) with per-key environment overrides ITAMBOX_PLUGIN_<NAME>_<KEY> for secrets, validated against the new settings_schema manifest attribute. settings_schema replaces default_settings and required_settings, which a plugin may no longer declare; unknown keys, missing required keys, wrong types and values outside choices abort startup with a message naming the plugin and the key, and keys flagged secret never appear in logs, diagnostics or errors. This includes the message of a startup error raised by plugin code and secret values of any length, including numbers.
  • migration_baseline_preflight recognizes v1.0.0-beta.5 (supported-predecessor-beta5) as the only predecessor state; the earlier pre-squash, transition-release and beta.3 states are removed. scripts/migration_audit.py now verifies that the replaces declarations on disk and the checked manifest agree, and the supported-upgrade qualification driver is scripts/qualification/migrations/run-supported-upgrade.sh.
  • The detail tabs and the card-header tabs (object lists, import, user profile) stay on one row and scroll horizontally instead of wrapping into up to three rows on narrow screens. The overflowing edge fades and a chevron marks the direction; the active tab is scrolled into view, and the bar joins the tab order exactly while it can scroll. The native scrollbar stays hidden because it reserves height and would lift the active tab's underline off the card border.

Security

  • The user detail, edit and delete pages now enforce the workspace tenant boundary. A non-superuser reaches only users who hold a membership in a tenant of their current workspace scope, exactly as the user list already did, and the permission is evaluated in a tenant the target user is actually a member of rather than in the actor's own tenant; a pk outside the scope answers 404. A password on an existing account is a global credential and is now restricted to superusers, like the staff, superuser and login-capability flags next to it, so it can no longer be reset through that page by a tenant-scoped role; creating a new account keeps its provisioning password.
  • Raised the dependency floors that carried open advisories: Pillow to >=13.0.0,<14.0 (was >=12.3.0,<13.0; nine advisories across fourteen alerts, including critical ones), certifi to 2026.10.19 and, through @graphiql/react, markdown-it to 14.3.3 in the browser bundle. The Pillow floor is a deployment requirement: an existing installation has to reinstall its Python dependencies before it starts.

Fixed

  • The bulk check-in, bulk check-out and bulk disposal entries are now offered where the scan pages actually accept them. In the all-accessible scope the mobile action bar offers them when at least one accessible tenant grants the permission, and the docked bulk-action toolbar offers them only to a user who holds it, instead of unconditionally; a concrete tenant scope still answers to that tenant's permission (issue #907).
  • Saving a different interface language on the user preferences page now reloads the whole page, so the sidebar, topbar, messages and page title are rendered in the new language immediately instead of staying in the previous one until the next manual reload (issue #909). A save that keeps the language keeps the in-place behaviour.
  • The dashboard Change Log widget's Hide Internal Event Entries option now hides the entries it promises to hide: background job bookkeeping (core.job changes) and system-generated changes with no acting user, next to the legacy extras.event exclusion. The option composes with the widget's action and object-type filters instead of replacing them, its help text states what it hides, and an installation that turns it off keeps the unfiltered feed (issue #913).
  • The global search page's "Object types" field lists the searchable models again, one entry per registered search index, so a search can be narrowed to a model type from the UI. The choices are read from the live search registry when the form is built instead of being captured at import time, before the per-app search indexes had registered (issue #919).
  • Unread notifications stay readable in the dark theme. An unread entry now marks itself with a theme-aware surface and a leading accent instead of a light-only tint plus a pinned dark subject colour, which had painted the subject dark-on-dark (1.1:1 measured) while read entries stayed legible; the membership, role and user-group detail pages also render their value headings in the body text colour instead of a fixed dark one (issue #921).
  • The sidebar's Bulk Actions group offers Bulk Check-out and Bulk Check-in again in the all-accessible ("All tenants") scope. The group gated them on an objectless assets.change_asset check, which that scope refuses because it has no tenant anchor, so only Bulk Disposal appeared even though the scan pages accept those actions with a target tenant the actor holds the permission in; the group now uses the same scope-aware decision as the scan views, the mobile action bar and the bulk-action toolbar (issue #923).
  • Resource grants link their usage page through the standard breadcrumb help button instead of a second, page-local Docs button. The list, revoke and expiry-run views declare document_path = "usage/resource-grants", so the one help entry point every page already renders points at that page, and the two templates that existed only to add the extra button are gone (issue #925).
  • The detail tab bar keeps every label visible on desktop again. A rule that collapses an inactive tab to its icon applied at every viewport width and overrode d-xl-inline, so the Subscriptions tab (and the other generic tabs) showed a bare icon next to model tabs that carry their label; the compact behaviour now applies below the xl breakpoint only (issue #927).
  • The camera scanner decodes EAN and UPC again in Firefox. The reader preferred the browser's native BarcodeDetector whenever it was present and the library never falls back on its own, while Firefox's detector answers QR codes but drops the 1D symbologies, so every 1D frame decoded to nothing; the native detector is now only used when it reports the full set the scanner promises (QR plus the 1D codes), and the bundled decoder handles the rest (issue #931).
  • The theme preference moved from the header into the user menu, where Auto / Dark / Light are one segmented control backed by a labelled radio group instead of two sun/moon buttons you had to cycle through. The workspace switcher now sits in the mobile header as a single briefcase button that opens the tenant list, so the drawer no longer carries a second switcher at its foot (issue #929).
  • The user menu no l...
Read more

ITAMbox v1.0.0-beta.4

ITAMbox v1.0.0-beta.4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Oct 20:01
Immutable release. Only release title and notes can be modified.
cd03bb2

Added

  • manage.py operational_health reports worker, scheduler, queue, cache, stuck-job and failure health with --json and --check (issue #587). Thresholds are configurable through the new optional ITAMBOX_HEALTH_* settings. /health/ keeps its database-only readiness contract, now pinned by tests. Read-only; no migrations.
  • manage.py export_catalogue_schema writes the JSON Schema (2020-12) of a community catalogue asset type, derived from the core specification vocabulary: flat model fields, category limited to the vocabulary categories, and a specs map limited to vocabulary keys with quantities in their vocabulary unit (for example 57 Wh). The generated file is committed next to the generator and a drift test keeps it equal to the vocabulary (issue #769). The community catalogue repository itambox-community/type-library keeps a byte-identical copy and validates every model file against it (issue #771).
  • The generic bulk import (preview, confirm, background job) imports catalogue asset types in that format (issue #770): each row's specs mapping is validated with the same rules as the generated schema before any job runs, category and asset_role are referenced by slug, a missing manufacturer is created only for an actor who may add manufacturers, rows are created through the canonical create_asset_type command, and an existing type is skipped and reported, never updated.
  • The asset overview shows a compact Recent activity card with the five newest timeline events and a link to the full timeline (issue #645).

Changed

  • Breaking: The in-app Type Library is removed (issue #768). The Type Libraries navigation entry, the /assets/type-libraries/ pages (list, import, detail, export) and the REST endpoints POST /api/assets/type-libraries/preview/, /apply/ and /export/ are gone and answer 404; library import, release history, reconciliation, snapshots and forks no longer exist. The read-only Library origin is no longer published: the library property of the REST Asset Type representation and the GraphQL AssetType.library field with its LibraryOrigin type are removed, and specification commands no longer lock library rows (the catalogue lock and the owner row lock are unchanged). The core vocabulary document drops its release envelope (kind, library) in favour of a plain version and label; its fields, fieldsets, choices and categories are unchanged. Reusable Asset Type models move to the community catalogue: one YAML file per model, imported through the regular bulk import (epic #772). The specification model is unchanged: managed core fieldsets, quantity kinds and units, ordered specifications with history and the core vocabulary keep working as before. The Asset Type columns lifecycle, deprecated_at and replaced_by existed only for the Library and are removed with it (they were neither shown nor filterable), and the extras.manage_specification_library permission and the Library model permissions are retired: the upgrade removes them from the permission table and from roles that carried them. No data migration is needed; Library tables are dropped empty.

  • Breaking: Repair episodes are replaced by the repair maintenance itself (issue #644). The RepairEpisode model, its /assets/episodes/ routes, its navigation entry, its form fields, its generic CSV export declaration and its permissions are removed; a repair is an ordinary AssetMaintenance of type repair, and that record anchors the whole story. Recording a repair can issue a loaner in the same submission: the loaner is checked out to the asset's current holder as a loan bound to that maintenance, with the due date defaulting to the expected completion, and the submission fails closed (writing nothing) when the unit is unavailable, belongs to another tenant, or the asset has no holder. Completing the repair offers Returned (the loaner is checked back in and the repaired unit is checked out to the same holder), Replace permanently (the loan stays with the holder as a regular assignment, optionally starting the disposal of the original unit in the same step, linked to the repair) or Do nothing; each reuses the existing checkout, check-in and disposal operations and their permissions, and an action the actor may not perform is not offered. AssetAssignment and AssetDisposal gain an optional maintenance link and the episode fields on maintenance, reservation and disposal are gone. The asset timeline groups records by repair maintenance and lists assignments and loans as events, and Log repair on the Timeline tab opens the maintenance quick-add with the repair type preselected. Upgrade: the migration maps every beta-era episode - a linked disposal moves to the episode's single repair maintenance, a linked stand-in becomes that repair's loan, and anything that cannot be mapped unambiguously (no or several repair maintenances, a reservation link, the episode notes, a substitute without a matching loan) is appended to the maintenance notes or written as a journal entry on the asset - reports the count per outcome, and leaves records that cannot be anchored standing and unlinked rather than dropping them.

  • Breaking: GraphQL is read-only. All Graphene write mutations (assets, inventory, licenses, software, subscriptions and asset specifications, 54 in total) and their input types were removed, and the built-in schema publishes no mutation root. Writes are REST-only. Migration for API consumers: use the existing REST resources for assets, inventory, licenses, software and subscriptions (including the subscription lifecycle and assignment actions); asset-type composition and category defaults through the asset-types actions (composition-preview, create-preview, apply-category-defaults-preview); and the new custom-field-choice-sets and custom-field-choices resources, whose writes (like custom field and fieldset writes) now run through the definition commands with If-Match resource revisions. Money values are decimal strings or numbers on REST, which also resolves the former createAsset(purchaseCost: 19.99) Decimal failure (issue #612).

  • The read-only GraphQL API moved from Graphene to Strawberry: graphene and graphene-django are removed and pinned to strawberry-graphql 0.328.x with strawberry-graphql-django 0.92.x (issue #613). The published schema keeps the previous contract unchanged — same /graphql/ route, token authentication, locally bundled GraphiQL, introspection for authenticated users, and the same 24 root query fields with the same types, fields, argument names, and nullability. Four documented differences accompany the port: a plugin's graphql_schema now expects Strawberry Query/Mutation types instead of Graphene ObjectTypes (the plugin API version stays 1.0, and a Graphene contribution is rejected and logged as a plugin failure instead of aborting core startup); the Date, DateTime, and Decimal scalar descriptions are reworded with unchanged wire behavior (Date/Decimal remain string scalars, DateTime stays ISO-8601); object types list their declared relations before the model fields and optional arguments print with an explicit null default (after: Cursor = null), leaving the type, field, and argument sets unchanged; and the former 500-field-selection cap is replaced by Strawberry's built-in MaxTokensLimiter (2000 tokens) and MaxAliasesLimiter (50) alongside QueryDepthLimiter (10) and the unchanged fan-out complexity budget (max complexity 2000, fan-out 10), while operations rejected before execution still answer HTTP 400 without a data member. assets/tests/test_graphql_schema_snapshot.py now pins the published SDL (fixture itambox/assets/tests/data/graphql_schema_text.graphql) together with the root-field contract.

  • Generic CSV/YAML/template export is now explicit opt-in and scope-safe (issue #585). Every installed model carries a reviewed data-transfer declaration; an undeclared or denied model answers 404 on every generic export path (CSV, YAML, template render, all, filtered and pk= scopes) instead of being exportable by default. Each exportable model declares the scoping the export must apply (tenant-scoped manager, shared reference data, container scoping via visible_to_containers, or owner-scoped personal rows), and the route requires the model's dedicated export_<model> permission in addition to view_<model> wherever one is declared, so the generic surface is never weaker than a dedicated export. compliance.CustodyReceipt and the other confirmed or same-pattern surfaces (custody signing sessions and handoff deliveries, compliance.AssetAudit, attachments, core.Job, core.RecycleBin, personal dashboards/bookmarks, saved filters, webhook endpoints and deliveries, sessions, tokens, permissions, OTP devices and background-task tables) fail closed; their dedicated surfaces remain authoritative. Export templates bound to a denied model are hidden from the content-type picker and answer 404 rather than downloading an empty or over-broad file. export_scope=all now documents and implements "every row the requester may see under their declared scope", never every row in the database.

  • reconcile_procurement_legacy reports pre-upgrade fulfilment pledges (requests that a partial receipt approved while delivered quantities were still untracked, with a blank qty_received); it classifies each pledge individually: candidates are pledges on partially received non-serialised lines whose own allocation exceeds the line's recorded received quantity, while completed records (assigned asset or fully received line) stay untouched and pledges the received units could cover in full, lines without receipt, and serialised lines without an asset require explicit operator review - --apply only softly closes the candi...

Read more

ITAMbox v1.0.0-beta.3

ITAMbox v1.0.0-beta.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 29 Sep 07:09
Immutable release. Only release title and notes can be modified.
c159636

Changed

  • Release images are published as a multi-platform index with linux/amd64 and linux/arm64 variants instead of an amd64-only image, so ARM64 hosts can pull the official tag directly; the release workflow builds both platforms from one reviewed commit, verifies both platform manifests fail-closed, and boot-checks both platform images before the draft release is prepared (issue #549).
  • The frontend build toolchain migrated from Node.js 20 to Node.js 26: the stylelint, frontend, and E2E CI jobs, the runner-validation workflow, the production image's frontend build stage (node:26-slim), and the contributor prerequisites in CONTRIBUTING.md now use Node.js 26.
  • Dashboard charts (asset status distribution and asset age distribution) are rendered with Apache ECharts instead of ApexCharts; categories, colors, tooltips, legends, empty states, light and dark theming, and the behavior across HTMX swaps and GridStack resizes are preserved, and crowded category labels rotate on narrow widgets the way the previous engine rotated them. The chart code is bundled locally with no runtime downloads and no CSP exception was added, and the ApexCharts dependency and its vendored script are removed entirely.

Fixed

  • Corrected the maturity statements in the documentation index and the SaaS Subscriptions model page to the declared capability grades: SaaS Subscriptions and Purchase Orders and Contracts are Stable; the report designer, scheduled reports, alert rules, webhooks, the Asset Request procurement seam, and SCIM provisioning remain Beta; the plugin system remains Experimental. No declared capability grade changed; only the published documentation was corrected.

Security

  • The published image installs the current openssl, libssl3, and tzdata security builds in its runtime stage instead of inheriting the stale base-image pins, clearing the medium- and low-severity findings that remained from the v1.0.0-beta.2 image scan.
  • The release gates now block on every unsuppressed image finding (--fail-on any) instead of only high and critical findings, so a cut can only pass from a scan-clean candidate; governed suppressions remain the only exception.
  • A scheduled drift scan rebuilds and rescans the current main image weekly, so new advisories surface between releases instead of only at the next release gate.

Known limitations and upgrade requirements

  • The supported upgrade origin for this release is v1.0.0-beta.2. Version skipping remains unsupported, and the earlier prereleases (v1.0.0-alpha.*, v1.0.0-beta.1) are not supported origins — run migration_baseline_preflight from the exact candidate checkout before any migration work.

ITAMbox v1.0.0-beta.2

ITAMbox v1.0.0-beta.2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 27 Sep 19:55
Immutable release. Only release title and notes can be modified.
e3f269e

Added

  • The Asset Type Library was finalized on the specification model: asset types compose an explicit, ordered list of fieldsets and fields with per-target applicability, the type-library vocabulary is pinned to a canonical core set, and the runtime serves exactly this vocabulary with no development-era compatibility layer left (issue #479).
  • Repair/replacement stories can be reconstructed as episodes: link maintenance records, reservations, and disposals to a repair episode (an asset plus an optional loaner/substitute) and read the grouped story on the asset detail Timeline tab (issue #504).
  • Asset holders gain a read-only Offboarding tab that gathers everything a departing person still holds across assets, inventory, licenses, custody receipts, subscriptions, and memberships; it replaces the removed offboard_user.py helper (issue #498).
  • Tagged releases now also publish the official container image to the GitHub Container Registry at ghcr.io/itambox/itambox-webapp:1.0.0-beta.2: the release workflow pushes the exact image it built, scanned, archived, and SBOM-validated, verifies the registry digest against that image, and attaches build provenance and the SPDX SBOM to it as OCI attestations. The downloadable archive, the standalone SBOM, and the registry image all describe the same reviewed commit.

Changed

  • Merged subscriptions.Provider into the shared assets.Supplier catalogue, now scoped by tenant or tenant group with null representing global scope; moved portal, account, and active fields onto suppliers, and made subscriptions reference suppliers directly with an optional procurement contract link. The cutover is a deterministic, upgrade-only migration with no compatibility aliases. This is a breaking prerelease change (issue #508).
  • Added supplier links for SaaS subscriptions and asset warranties, documented when to use Contracts versus Subscriptions, and distinguished agreement entitlement quantities from linked-license seat counts in subscription details and reports (issue #500).
  • Added the read-only migration_baseline_preflight release gate and checked manifest. The gate recognizes the current normalized baseline and the two supported predecessor states (supported-predecessor-pre-squash, supported-predecessor-transition-release) as exit-0 outcomes; partial, old, or mixed states are rejected before a cleanup attempt, and restore-first handling for interrupted non-atomic migrations is documented.
  • Normalized the migration history for the #479 release: the two #479 development waves and the replaced issue-#88 originals are gone, fresh installs and both supported predecessors (pre-squash and transition release) migrate to the same final schema, and the checked baseline manifest moves to the normalized layout (issue #479). The supported-upgrade qualification driver is checked in at scripts/qualification/migrations/run-supported-upgrade-p1p2.sh.
  • Forwarded client-IP handling is explicit and opt-in in production: ITAMBOX_RATELIMIT_USE_X_FORWARDED_FOR and ITAMBOX_RATELIMIT_NUM_PROXIES configure trusted-proxy client IPs, while directly reachable deployments stay fail-closed.
  • Release preparation from main now requires the app-owned end-to-end qualification suite to pass on the dispatched commit before the draft release is prepared.
  • Scope switching preserves list context: search, filters, and paging survive a switch, scope-bound filters are dropped with a visible notice instead of an empty list, a switch from an object page lands on the list instead of a 404, and aggregate bulk confirmations name each object's tenant. The platform-wide scope is labelled All Tenants (superusers: Global View), and users can choose a personal default workspace for a tenant, tenant group, or aggregate view (issue #499).
  • Tightened the first organization/membership English copy: role-form guidance, the assign-users explanation, member-selection help, role presets, and user-group help are shorter and more direct; the role assignment page and the permissions-matrix help now render reviewed German translations (part of issue #386).
  • The first German asset UI text chunk uses the established glossary terms and clearer labels for asset types, locations, custody receipts, and warranties.
  • Tightened the first English asset/request text slice: selection errors, request labels, custody notifications, disposal guidance, and bulk receiving copy are shorter and more direct without changing behavior.
  • The desktop footer keeps its timestamp and version stamp without the optional Tabler theme credit; the full application footer is hidden below the mobile action-bar breakpoint.

Fixed

  • The demo seed dataset now tells stories the product can actually produce: a received purchase-order line materialises an asset for every unit it reports, a repair episode is preceded by the check-in that removed the device from its holder (and the device is handed back afterwards with the status it had before the re-checkout), out-of-service maintenance documents a repair window the asset's own change log recorded, and an approved asset request always carries a tenant and an allocated unit that is actually claimable. Repaired units are no longer left stranded in a repair episode whose window never closed, and seeded assignments can no longer run backwards, start before their asset was bought, or return from the future. The self-check reads a repair window from the repair label itself rather than the pending meta-type that In Transit and Quarantined share, closes the window at the transition that leaves repair instead of at the asset's last change of any kind, and treats an assignment that overlaps the window at any point as a contradiction rather than only one open when it began; a unit already allocated to an open request is left unreserved so that a reservation for a different holder cannot dead-end the claim. A seed self-check fails closed when any of these regresses (issue #506).
  • The demo seed writes no placeholder signature payloads for accepted custody receipts, and the full-seed qualification covers the custody-receipt story end to end (issue #407).
  • Disposal history is preserved through explicit cancellation: a cancelled disposal keeps its record with reason, actor, and timestamp, the asset returns to Pending, a later disposal becomes a new historical record, and effective report totals exclude cancelled rows while the history stays visible (issue #496).
  • The dashboard target picker offers every canonically authorized live tenant (including managed-only MSP reach), renders each target independently of the ambient tenant, and fails closed for inaccessible, deleted, or revoked targets instead of falling back to ambient data (issue #447).
  • The asset creation form now accepts a blank asset tag and generates one from the tag sequence on save, matching the model contract and the PO receiving, bulk receive, import, and clone paths (issue #503).
  • Scan baskets now report an EAN that maps to several assets distinctly instead of claiming no asset matches, directing the operator to scan the asset tag (issue #502).
  • Subscription annual cost now annualizes multi-year terms over their length and one-time purchases are labeled as a one-time cost instead of occupying the annual slot; zero-cost subscriptions display 0.00 instead of an omitted row or "Not set" (issue #501).
  • Component Allocation create and asset quick-add are now explicitly target-only, reject silently ignored source locations, return observable HTMX success/errors, count source-backed Component checkouts only once in availability, and keep component/source/destination immutable on update (issue #393).
  • Tenant-scoped pages purge pre-existing HTMX session history snapshots and no longer save new ones, preventing stale asset actions from targeting objects outside the current server-side scope or retaining tenant DOM after a workspace switch (issue #419).
  • Asset list pagination now limits assignee resolution and tenant-scoped related-manager work to the rendered page instead of evaluating every asset in the active scope (issue #416).
  • Asset edits no longer clear purchase and in-service dates when localized HTML5 date controls are submitted after changing the tenant, location, or another field (issue #391).
  • Managed-tenant onboarding now gives the creating provider administrator explicit administrator reach and switches directly into the new tenant without adding a customer membership.
  • Tenant creation now exposes only object-authorized live provider tenants to eligible non-superusers, requires an explicit provider when one is available, and uses the same onboarding projection for normal and managed-tenant routes (issue #405).
  • Asset reservation quick-add now preserves a native POST fallback from asset detail pages instead of submitting a GET request (issue #390).
  • List page refreshes no longer emit an HTMX htmx:oobErrorNoTarget console error when the applied-filter count badge is updated: the filter-toggle badge now carries the filters-applied-count target id that the list refresh out-of-band swap expects, so applying, clearing, loading, or saving list filters update the visible count cleanly (issue #421).
  • Bulk check-in, check-out, and disposal keep their pre-seeded baskets when a target tenant is selected in an aggregate scope; every submitted asset is validated as a live asset of the bound tenant before any job is created, and job lists and cancellation follow the accessible-tenant scope in aggregate scopes (issue #424).
  • Non-staff users with tenant-scoped asset request permissions can now see and use their authorized actions consistently in tenant, tenant group, and All-accessible scopes: fulfilment actors record the handover from the request detail page, the bulk-receipt toolbar follows the per-request decision, and malformed or repeated selections report a message instead of an access-denied page (issue #497).
  • A...
Read more

ITAMbox v1.0.0-beta.1

ITAMbox v1.0.0-beta.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 16 Aug 19:40
Immutable release. Only release title and notes can be modified.
8d13721

Added

  • Scheduled reports with a cross-tenant scope now have an operator approval workflow: the schedule list shows the scope approval state, and a dedicated Scope Approval page approves or revokes the durable authorization (reports.view_cross_tenant_reports). Revocation keeps the approval history and fails delivery closed until a fresh approval covers the full scope.
  • Resource grants can expire: expiry dates drive a system revocation sweep, and a scoped audit API exposes the grant-expiry history (issue #195).
  • Webhook delivery is durable and observable: deliveries run through a state machine with retry handling and typed per-attempt outcomes instead of fire-and-forget sends (PR #349).
  • The production GraphQL surface enables schema introspection for authenticated users and exposes an authenticated GraphiQL interface (PRs #372, #376).

Changed

  • The report-designer opt-in flag is now ITAMBOX_FEATURE_REPORT_DESIGNER; ITAMBOX_REPORT_DESIGNER_ENABLED remains a deprecated 1.x fallback. When the flag is off, scheduled delivery is skipped for non-grandfathered templates, while the migration-managed bounded grandfathered set continues to render and deliver; grandfathered templates are read-only until the designer is enabled.
  • Event Rule conditions were withdrawn for 1.0: unsupported conditions fail closed and existing rows are preserved (issue #187).
  • Alert-channel delivery now records typed, observable outcomes per delivery attempt (issue #185).
  • Tenant-surface SCIM group reads require the users.view_usergroup permission (issue #193).
  • Accessibility was qualified across full-page and HTMX interaction journeys, and the remaining review gaps were closed (issue #101).
  • The runtime image refreshes its CA-certificate bundle during the build (issue #370).

Fixed

  • API token lifecycle: the key is shown once at creation, responses carry ETags, deletion works without a queryset, owner transfer returns 200, and creation without an active tenant fails closed (issues #341, #353).
  • User configuration and asset-tag-sequence endpoints reject unknown request fields instead of silently ignoring them (issue #344, PR #354).
  • OPTIONS on collection endpoints no longer raises 500 (issue #340).
  • API root and API namespace root discovery return 200 for authenticated users instead of 500 (issues #345, #363).
  • Scanner lookup resolves across all accessible tenants and accepts EAN/GTIN codes in every scan flow (issue #367).
  • Frontend: page headers stack actions on mobile, the mobile header/footer order and sidebar search are corrected, the dashboard switcher aligns with the action row, and mobile dashboard changelog cards carry field headings (PRs #365, #366, #368, #373, issue #374).

Security

  • Dashboard creation through the API sets the owner from the request context and rejects owner spoofing (PR #352).
  • The runtime image pins a patched nanoid dependency instead of the vulnerable override.

ITAMbox v1.0.0-alpha.3

Pre-release

Choose a tag to compare

@github-actions github-actions released this 12 Aug 21:23
Immutable release. Only release title and notes can be modified.
7741a72

Added

  • Added a shared typed external-integration error contract with retryable/terminal classification, safe user messages, bounded Graph retry handling, structured tenant/actor/request context, and documented follow-up boundaries for other adapters.
  • Added the versioned webhook envelope v1 with additive schema_version, event_id, delivery_id, attempt, and owning-tenant fields across generic, Slack, and Teams payloads; strict additional-property validators must update their schemas.
  • Published the 1.x compatibility, deprecation, and support policy together with a bounded external-contract inventory covering REST/GraphQL/SCIM surfaces, the webhook envelope, persisted choice values, contract-bearing settings, permission codenames, UI URL namespaces, and each capability's contract class and exclusions. A stdlib gate derives every enumerated surface from source and fails when the published contract and the code disagree.
  • Added explicit Purchase Order lifecycle endpoints at /api/procurement/purchase-orders/{id}/approve/, /order/, /receive/, /cancel/, and /reopen/.
  • Published the bounded procurement Stable qualification matrix, including existing UI, REST, service, tenant, permission, audit, currency, and PostgreSQL concurrency guarantees plus the deliberately absent surfaces.
  • Added explicit, opt-in Event retention controlled by ITAMBOX_EVENT_RETENTION_DAYS, with observable pruning of expired events.
  • Added opaque SCIM resource IDs and per-domain scoped externalId values; the previous identifier scheme remains readable through a 1.x dual-read window.

Changed

  • Intune discovery now records typed integration failures with safe user-facing messages and structured tenant-scoped job-log context; optional detected-software degradation is explicit in the completed result as software_degraded.
  • Qualified the four-state Subscription lifecycle as Stable across model, UI, REST, GraphQL, import/export, assignment, seat-accounting, and daily-task boundaries, including idempotent retries and model-level tenant validation.
  • Subscription status is now a closed four-state lifecycle (active, suspended, cancelled, expired) driven by explicit UI, REST, GraphQL, admin, and background actions. The canonical renewal-term field is vendor_contract_auto_renews; auto_renewal remains a 1.x read/write API compatibility alias.
  • Purchase Order status and Purchase Order Line qty_received are read-only in the REST schema. API clients must use the corresponding lifecycle endpoint: differing direct writes now return HTTP 400 with sanctioned-action guidance, while identical values remain accepted and ignored for full-representation PUT compatibility. Existing rows require no migration.
  • Asset Request auto-approval and the Beta Asset Request procurement seam are now opt-in through ITAMBOX_REQUISITION_AUTO_APPROVAL_THRESHOLDS; fresh deployments leave requests pending. The legacy setting name remains a deprecated 1.x fallback with a startup warning.
  • Alert rules with no configured channels now deliver nowhere instead of implicitly fanning out to every enabled tenant or tenant-less channel; platform-global in-app delivery remains explicit.
  • Closed the Event action vocabulary: EventRule.events is validated against the supported action set ahead of the 1.0 contract freeze.
  • Scheduled reports are gated on the report designer opt-in: with the designer disabled, the navigation entry is hidden, all scheduled-report routes return 404, and the background task fails closed while preserving saved rows.
  • Completed the zero-error OpenAPI generation contract and the generated-client compatibility check.
  • Updated locked runtime dependencies to redis-py 8.1 and django-redis 7.0.

Fixed

  • Made invalid generic list filters fail closed to an empty result while retaining field-level validation errors across full-page, HTMX, direct-query, and saved-filter requests.
  • Serialized concurrent Purchase Order approvals so only one draft-to-approved transition succeeds, and preserved the Purchase Order currency on assets materialized by receiving.
  • Scheduled-report runs now preserve their failure status and the original exception, keeping failed deliveries observable.
  • Corrected the alert-channel delivery documentation to match shipped behavior (synchronous, single-attempt delivery).
  • Made SCIM capability metadata truthful: removed the fake HTTP Basic capability, fixed User.lastModified handling, and wired request-id propagation.
  • Custom (non-CRUD) permissions declared via Meta.permissions are now exposed in the role editor, making actions such as preparing and exporting custody receipts grantable through the UI.
  • A valid signing session now overrides the seven-day custody bearer-link TTL, restoring assisted handoff on receipts older than seven days.
  • Fixed custody handoff UI issues: QR codes have a proper quiet zone, the handoff panel is mobile-safe, actions wrap on small screens, Bootstrap collapses rebind after HTMX swaps, copy feedback is sticky with a clipboard fallback, and custody export links are no longer htmx-boosted.
  • Fixed frontend issues: app-external links (docs, API, GraphQL, admin) are no longer htmx-boosted, the report preview button no longer leaks across pages, theme-token changelog panels and mobile stacking render correctly, Purchase Order and Resource Grant labels are localized, the responsive asset shell cleanup is complete, and scanner camera detections are throttled through one shared gate.

Security

  • Hardened the Intune Graph boundary against cross-registration token-cache reuse, bearer forwarding through redirects or untrusted @odata.nextLink hosts, provider-controlled device-ID path pivots, stale token lifetimes, and credential/payload leakage in exception and job logs.
  • Added cross-tenant read/write matrices for contracts, Purchase Orders, and Purchase Order lines together with real two-connection receipt and approval race tests.
  • Centralized Asset Request-to-Purchase Order linking in a tenant-locked, permission-checked, idempotent service and made failed UI linking roll back the new purchase order.
  • Removed the unused global pip installation and ensurepip bootstrap from the production runtime image, with build-time checks that the copied runtime environment remains pip-free, while preserving locked uv-based dependency resolution in the builder.
  • Global cross-tenant report aggregation is now permission-gated; the curated built-in report contract remains unchanged.
  • Froze and proved the tenant resource-grant security boundary with cross-tenant read/write matrices and adversarial coverage.
  • Removed the remaining unsafe-inline style dependency from the Content Security Policy and restored runtime dashboard styles under the hardened policy.
  • Remediated the dependency security-gate findings in the locked dependency set.

ITAMbox v1.0.0-alpha.2

Pre-release

Choose a tag to compare

@github-actions github-actions released this 12 Aug 21:23
Immutable release. Only release title and notes can be modified.
9b77b1e

Added

  • Added deterministic CI ratchets for test coverage and certification, changed-code coverage, local imports, exception handling, OpenAPI diagnostics, architecture layers, and import cycles. Existing debt is explicit and cannot grow silently.
  • Added an architecture decision record and contributor guidance for module layers, approved import directions, inline-import annotations, exception boundaries, and the supported public plugin API.
  • Added focused security and authorization regression coverage for generic views, membership and role-grant services, login and tenant SSO entry points, inventory stock actions, and asset-form scoping.

Changed

  • Standardized Python formatting and import ordering with Ruff, reduced selected function complexity, and paid down selected findings while preserving the existing deterministic flake8 no-growth ratchet.
  • Stabilized generic detail, list, create, edit, delete, and service-action views around fail-closed authorization checks, and standardized HTMX success responses for restore and service actions.
  • Extracted membership and role-grant operations from presentation forms into explicit organization services with tenant-, container-, and delegated-scope enforcement.
  • Consolidated accessory, consumable, and component stock actions on shared transactional services and authorization checks.
  • Decomposed AssetForm initialization into focused collaborators while preserving tenant scoping, initial-value precedence, and validation behavior.
  • Made OpenAPI generation deterministic and checked in the canonical schema plus a warning/error identity baseline.
  • Made the daily subscription expiry/reminder task enumerate all tenants and use the local date, avoiding tenant omissions and one-day boundary drift.
  • Updated locked dashboard and Django integration dependencies to GridStack 13.1.2, django-filter 26.1, django-htmx 1.28.0, and django-otp 1.7.0; refreshed frontend build and browser-test tooling and added browser coverage for GridStack initialization, resizing, and persisted layouts.

Fixed

  • Hardened login and tenant SSO entry points against stale tenant selection, unsafe fallback behavior, ambiguous provider routing, and signing-algorithm drift; corrected the documented tenant OIDC routes.
  • Replaced security-sensitive silent exception handling with explicit, justified boundary behavior and a blocking policy gate.
  • Removed an accidental internal gap report from release source archives.
  • Updated PostCSS and brace-expansion dependencies past their reported security advisories.

Security

  • Added fail-closed authorization tests around shared action views, membership and RBAC mutations, tenant selection, SAML POST handling, and OIDC provider validation.
  • Escaped configurable AssetForm tag-prefix help text so crafted values cannot break HTML attributes or inject active SVG markup.
  • Made domain-model -> presentation imports unconditionally forbidden and made new module-top or deferred import cycles fail CI.
  • Required every retained broad/silent exception, local import, cycle, and cross-layer dependency in the scanned production scope to carry a reviewable identity or inline justification.

Known limitations and upgrade requirements

  • The architecture, exception, local-import, OpenAPI, lint, and coverage baselines intentionally freeze pre-existing debt; they prevent growth but do not claim that the recorded debt is already removed.
  • Upgrades from deployments that used arbitrary passphrases in ITAMBOX_FIELD_ENCRYPTION_KEYS must carry forward the exact previously derived Fernet key. Substituting a replacement key makes existing encrypted secrets unreadable; follow the installation guide before deploying this alpha.
  • ITAMBOX_TENANT_LDAP_CONFIGS, ITAMBOX_TENANT_SAML_CONFIGS, ITAMBOX_TENANT_OIDC_CONFIGS, and ITAMBOX_TENANT_INTUNE_CONFIGS must contain JSON objects. Malformed JSON or non-object values now stop startup with ImproperlyConfigured instead of silently disabling the integration configuration.
  • Review tenant-specific SAML and OIDC mappings before upgrading. SAML requests now require a live, configured tenant; a default SAML configuration is accepted only when exactly one live tenant makes it unambiguous, and missing, deleted, or inactive tenant bindings return 404.
  • SaaS subscriptions, procurement, reporting, webhooks and event rules, SCIM, and the plugin lifecycle remain Beta. Their interfaces may change during the prerelease series.
  • Alpha upgrades may include breaking migrations. No general version-skipping policy exists yet; review and test the exact target revision with a complete backup and rollback plan.
  • The full pytest suite is not safe to run with pytest-xdist; use the default serial configuration.
  • SQLite is not supported. PostgreSQL 15 or newer is required for development, tests, and production.

ITAMbox v1.0.0-alpha.1

Pre-release

Choose a tag to compare

@github-actions github-actions released this 24 Jul 15:42
Immutable release. Only release title and notes can be modified.
917ac1c

ITAMbox 1.0.0-alpha.1

This is the first tagged alpha of ITAMbox: a self-hosted, multi-tenant IT asset-management platform for internal IT teams and managed-service providers.

It is a limited-audience prerelease. The repository is public, but this release is intended for evaluation and early feedback—not a production-support commitment.

What you can do today

  • Manage the asset lifecycle: Catalog hardware, assign and check assets in or out, reserve equipment, track warranties, maintenance, depreciation, disposal, and cost history.
  • Run location-aware inventory: Manage accessories, consumables, components, and kits with barcode/QR workflows, transactional stock operations, imports, exports, and bulk actions.
  • Track software and spend: Maintain software catalogs, installed-software records, license seats, suppliers, cost centers, subscriptions, purchase orders, contracts, and fulfillment links.
  • Operate across tenants safely: Use tenant roles, groups, delegated resource grants, and scoped administration for MSP and multi-organization environments.
  • Support custody and audits: Create custody receipts with digital sign-off, run audit campaigns, reconcile records, preserve audit evidence, and export results.
  • Integrate and extend: REST APIs with OpenAPI/Swagger UI/ReDoc, a scoped GraphQL API, CSV tooling and Snipe-IT migration support, LDAP/SAML/OIDC sign-in, Intune discovery sync, and Beta SCIM provisioning and plugin extension points.

Built for accountable operations

This alpha includes auditable change records, tenant-aware background jobs, search, tags, custom fields, dashboards, reports, alerts, webhooks, notification channels, and a German-localized PWA experience.

The deployment path is a production-oriented Docker Compose stack with PostgreSQL, Valkey, a background worker, health checks, and an isolated smoke test. Python dependencies are locked with uv so Docker, CI, and contributors resolve the same versions.

Security and release qualification

ITAMbox enforces tenant boundaries across UI, REST, GraphQL, imports, bulk actions, attachments, and downloads. This release also includes hardened delegated authorization, hashed and rotatable API tokens, encryption for protected settings and secrets, webhook SSRF defenses, TOTP enforcement for privileged local accounts, rate limiting, SAML replay protection, secure upload validation, and a nonce-based script CSP.

The tagged commit passed the full hosted CI suite, E2E and Docker smoke tests, security and CodeQL gates, a release-image Trivy scan, and independent archive checksum verification. Backup/restore and migration-parity qualification are documented as part of the alpha baseline.

Before you evaluate

  • Use PostgreSQL 15+. SQLite is not supported.
  • Prefer the documented Docker Compose path; the release archive is a reviewed image candidate, not a public container-registry image.
  • Treat upgrades as potentially breaking during the alpha series. Take a complete backup and test the exact target revision before upgrading; version skipping is not supported yet.
  • SaaS subscriptions, procurement, reporting, webhooks/event rules, SCIM, and the plugin lifecycle are Beta and may change before 1.0.
  • The full test suite currently runs serially; pytest-xdist is not supported.

Documentation and technical detail

Please evaluate in a disposable or fully backed-up environment and report feedback through GitHub Issues.