Release Notes
What's new, fixed, and improved in each DocuMan release. Newest first.
v2026.06.08
2026-06-08
Fix AI cabinet settings not loading saved indexes
Critical follow-up to v2026.06.07. Saving a cabinet's AI settings
(including selected indexes) returned a green
"AI Settings Saved" confirmation, but reopening the
cabinet showed the indexes empty again. The write actually
succeeded — PostgreSQL stored the JSONB array correctly
— but the read path returned the value to the frontend as
a raw JSON string instead of an array. The browser's
Array.isArray check rejected the string and fell
back to an empty list, making it look like nothing had saved.
The fix registers a JSON / JSONB codec on the asyncpg connection
pool (backend/app/database.py) so reads and writes
both round-trip through Python lists and dicts cleanly. The
four callers that previously pre-serialized with
json.dumps were updated to pass their values
directly. Audit logging, login-failure tracking, the Review
Queue Fix endpoint, and cabinet AI settings all share the same
codec now.
No data was lost — index selections that appeared empty
on reload are still in the database. After upgrading, reopen
any affected cabinet and the saved indexes will display as
expected.
Security Browser close now ends the session
Auth tokens now live in sessionStorage instead of
localStorage. Closing the browser entirely (not just
the tab) wipes the session, so reopening the app lands on the
login screen. Previously the token persisted across browser
restarts. The username-remember preference still uses
localStorage — that's a UX convenience, not
auth state. Orphan tokens left over in localStorage
from earlier installs are scrubbed on next sign-out.
Improvement <MatchCheckCompany> is now a selectable index
The folder-matching token has existed in the worker and the
variable autocomplete for a while, but it was missing from the
index catalog, so there was no way for an operator to opt into
it. Added it as a Document Fields index. Because it
shares ai_field=company with <Company>
and <CompanyFirstLetter>, the primary
extraction call still asks for the company name exactly once. A
tiny second-pass AI call fires only when the resolved template
actually contains <MatchCheckCompany> —
it picks the best existing sibling folder under the parent path
(e.g. "Minink Materials, LLC" reuses an existing "Minink" folder
instead of creating a separate one).
Improvement Help sidebar shows selected document fields
The right-side help reference in the Cabinet Properties dialog
now includes a Document fields section listing every
field-type index you've selected (<Company>,
<CompanyFirstLetter>,
<Amount>, the ID tokens, your custom indexes,
…). The list stays gated to your selection —
unpicked variables don't appear, so the panel still only shows
what's actually wired up to resolve in templates.
Improvement Scan Time token catalog cleaned up
Removed redundant aliases from the <Now*>
tokens: <NowYear>, <NowMonth>,
<NowDay>, and <NowISO> are
gone. Use the canonical short forms instead:
<NowYYYY>, <NowMM>,
<NowDD>. Templates that used the old tokens
will no longer resolve them — switch to the canonical
names. Every other Now token (date, time, hour, minute, second,
quarter, week number, month name, day name, millis / micros /
nanos, full epoch values) is unchanged.
v2026.06.07
2026-06-07
Improvement Cabinet AI dialog: per-variable index picker, independent column scroll, default Company
Refinements to the AI Watch Folder index system introduced in
v2026.06.05:
- Per-variable indexes. Every template variable
is now its own selectable index —
<Company> and
<CompanyFirstLetter> are separate checkboxes,
as are <DocYear>, <DocMM>,
<DocQuarter> and the other date components.
The Document Date section in the picker is sub-grouped (Full date
forms / Year / Month / Day / Quarter & week) so the longer
list stays readable. The AI request still dedupes by underlying
field, so selecting many date variables still asks the model for
the date exactly once.
- Custom (per-cabinet) indexes. The Choose
Indexes dialog has a new Custom (this cabinet) section
with + Add custom index. Each custom index has a
name (the template token, e.g.
PatientChartNumber),
a display label, and a description that becomes the AI's
extraction rule. Custom variables show up in the
< autocomplete on both template inputs.
- Independent column scroll on the AI tab. The
help sidebar on the right and the form on the left now scroll
independently — reading the help reference no longer drags the
form past where you were editing. The whole Cabinet Properties
dialog also grew a bit (1340 px, 96% of viewport height).
- Help reference filters to your selection.
The Filing help on the right side only lists variables from
indexes the cabinet has actually selected, with a standout
callout at the top making the rule obvious. No more wading
through 80 tokens to find the three you've picked.
- "Document fields" help section removed.
Every variable previously listed there is now an index — no
point listing them twice.
- Cleaner index chips. Selected indexes
display as rectangular tags on the AI tab (light blue for
AI-extracted, grey for computed, dashed orange for custom)
instead of pill-shaped chips.
- New cabinets default-select Company. The
Indexes section is no longer empty on first open — Company is
pre-checked and can be unchecked like any other index if the
cabinet doesn't need it.
- Review Queue: combined date input. No
matter how many date variables a cabinet has selected, the
review-queue editor shows one Document Date field; the
backend re-derives year, month, day, quarter, week, etc. from
that single value when you click Fix. Non-date
variables each have their own editable row, and
<CompanyFirstLetter> stores under its own key
so you can override the derived first letter independently of
the full company name.
No reconfiguration required after upgrading: migrations 064-067
re-parse each cabinet's folder + filename templates and
pre-populate the matching per-variable indexes automatically.
Existing v2026.06.05 installs skip the already-applied
migrations and pick up only the code changes.
v2026.06.05
2026-06-05
New AI extraction "indexes" — pick exactly what the AI sees
Cabinet AI is now driven by a small list of indexes
you opt into per cabinet — each index covers one logical field
(Company, Document Date, Invoice Number, Amount, etc.). Only the
indexes you select are requested from the AI, and only their
template variables resolve in your folder + filename templates.
Computed indexes (Scan Time, Import Date, Original Filename) are
always available with no AI cost.
- New fields: Invoice Number, PO Number, Account
Number, Reference / Tracking Number, Customer / Patient ID,
Vendor Code, Description / Summary, Subject / Title, and Currency
— with matching
<InvoiceNumber>,
<PONumber>, etc. template variables.
- Choose Indexes… dialog: a new picker
(Cabinet Properties → AI Auto-Import → Indexes) lets
you check-mark exactly which indexes this cabinet uses. Selected
indexes appear as chips on the AI tab.
- Smarter Document Date: the AI is only asked
for the date once (as
ref_date); every Doc*
subfield (<DocYear>, <DocQuarter>,
<DocWeekNumber>, …) and all smart-date
variants are derived locally. No tokens get to the AI that don't
need to.
- Cleaner system prompt: the JSON response
schema is generated automatically from your selected indexes and
appended to the prompt. The prompt textarea is now just for
describing what kind of documents this cabinet files — no
more hand-maintaining the JSON shape.
- Automatic migration: existing cabinets get
their
selected_indexes pre-populated by parsing the
tokens already in use in their folder + filename templates. No
manual reconfiguration after the update.
New Editable indexes + "Fix" on the Review Queue
When the AI's extraction needs a correction, you can now edit the
values inline on each pending review-queue item and click
Fix to re-run the folder + filename templates
with the corrected values — no extra AI call. The filename
is always editable independently, and any date you correct is
shown as a single date input (the worker derives year, month,
quarter, week-number, … locally).
After you approve a document, every index value is mirrored into
its document tags so the same data stays queryable on the
document itself long after the review-queue row is gone.
v2026.06.03
2026-06-03
New Smarter AI Watch Folder template variables
The folder- and filename-template fields now know about a much
wider set of variables, an autocomplete that surfaces them as you
type, and an inline help panel that documents every one with an
example.
- IntelliType (< autocomplete) — type
< in either template field and a menu of every
supported variable appears, filtered as you keep typing
(<Doc narrows to the document-date set, etc.).
Arrow keys + Enter to insert, Escape to cancel.
- Richer document-date set —
<DocYYYY>, <DocYY>,
<DocMM>, <DocDD>,
<DocMonthName>, <DocDayName>,
<DocQuarter>, <DocWeekNumber>,
and <DocISO> alongside the existing
<DocDate> family.
- Scan-time ("Now") variables with nanosecond precision
—
<Now>, <NowDate>,
<NowTime>, <NowISO>, all the
date/time component tokens (<NowYYYY>,
<NowMM>, <NowHH>, …), plus
<NowMillis> / <NowMicros> /
<NowNanos> and full epoch values up to
<NowEpochNanos> for unique-by-time filenames.
- <MatchCheckCompany> — a new variable
that fuzzy-matches the AI-extracted company name against existing
subfolders. Example template
/Packing Slips/<CompanyFirstLetter>/<MatchCheckCompany>
with an AI-extracted company of "Minink Materials, LLC"
files into the existing Minink folder instead of
creating a separate "Minink Materials, LLC" folder. A
strict deterministic second AI call picks from the candidate list,
with post-filtering so the model can't return a name that wasn't
offered. Triggers only when this variable is in the template
— no extra AI cost otherwise.
Improvement AI cabinet settings can't be configured until enabled
Every field on a cabinet's AI Auto-Import tab
(watch folders, templates, prompt, auto-approve, vision settings)
is now disabled until the Enable AI Auto-Import
toggle is on. A small notice points at the toggle. This makes the
"fill everything in but forget to flip the switch" mistake
impossible.
Improvement Watch folder root mode is no longer a footgun
Creating a Watch Folder without picking a target folder used to
silently file loose files into an auto-created Inbox
folder — with no UI hint that this would happen.
Administration → Watch Folders now:
- Shows a clear banner in the add-folder dialog explaining that
root-mode files go to an auto-created Inbox folder in the
cabinet and that subdirectories become top-level folders.
- In the watch-folder list, root-mode rows show
"→ Inbox (auto)" as their target, with a tooltip
describing the behavior.
Fix Folder permission inheritance UI
The folder-properties Permissions tab had several
bugs that combined to make the "Inherit permissions from parent"
checkbox feel broken. All addressed in this release:
- Route shadowing bug — the
/permissions/folder-inheritance/{id} endpoint was
being shadowed by a more-general catch-all route registered first,
so the API silently returned an empty list. This made the
checkbox always appear unchecked regardless of the database
state. Routes are now ordered so specific paths win.
- Inherited permissions are now displayed in
the folder properties (Windows-Explorer style). When a folder
inherits, the permission table shows the inherited rows directly,
dimmed and read-only, with a caption that says "Showing
permissions inherited from cabinet 'X'." No more clicking back up
to the parent to find out what's in effect.
- Indeterminate checkbox — the checkbox
could render as a "—" dash with no apparent way to interact with
it. The state is now coerced to a clean boolean and Quasar's
tri-state click cycle is disabled.
- "Break inheritance" Cancel button — the
confirmation dialog's Cancel button used to mean "no, don't copy
parent perms — but still break inheritance," which was a trap. The
flow is now two confirmations: the first asks whether to break
inheritance at all (Cancel is a true no-op), the second
chooses the starting permission set.
Fix Spurious "permission denied" toast on file rename
Non-admin users whose access came via group membership saw a red
"You do not have permission to perform this action"
notification when they opened a document's Properties dialog,
even though the rename itself worked. The cause was a separate
/admin/users + /admin/groups request
fired to populate permission-picker dropdowns — admin-only
endpoints that 403 for non-admins, tripping the global error
toast. Those requests are now skipped for non-admin users (the
dropdowns are only useful to admins anyway).
v2026.05.28
2026-05-28
Improvement Cleaner Settings page
The admin Settings page no longer duplicates options
that already have their own dedicated pages. Those settings are still
fully editable — just from a single place each — which
removes the risk of two editors disagreeing about the same value. The
general Settings table now stays focused on truly general options
(OCR, uploads, session timeout, and the like).
- Backup settings (destination, schedule,
retention,
pg_dump path) are managed only on
Administration → Backups.
- Consistency-check settings (schedule,
email-on-failure,
pg_amcheck path) are managed only on
Administration → Consistency.
- Directory / single sign-on settings (LDAP, Active
Directory, and Microsoft Entra ID / Azure) are managed only on
Administration → Active Directory.
- These now follow the same rule the SSL/certificate settings
already did — if a setting is owned by a dedicated page, it no
longer appears in the general Settings table.
v2026.05.27
2026-05-27
Security Permission hardening
This release tightens how per-user permissions are enforced across
cabinet visibility, search, and login. Upgrading is
recommended for all installations.
- Cabinet visibility — users no longer see
the names of cabinets they have no permission on. This applies to
the left navigation tree, the search-page cabinet filter, and the
AI Review Queue cabinet filter.
- Search — full-text and advanced search
results are now strictly scoped to the caller's permissions. Hits
from cabinets the user has no access to are no longer returned,
even when a cabinet or folder ID is supplied directly.
- Login — a valid Active Directory account
alone is no longer sufficient to obtain a session. Users must be a
system administrator or have at least one cabinet permission
(direct or via group membership) for the login to succeed.
Rejected attempts are recorded in the audit log.
- Per-login group sync (AD & Azure SSO) —
every successful sign-in now re-reads the user's directory group
memberships and reconciles them in DocuMan. Adding a user to a
permitted group in AD takes effect on their very next sign-in;
removing them revokes access immediately. Manually-managed (non-AD)
group memberships are untouched.
- UI affordances — the "New Cabinet" and
"New Folder" buttons are now greyed out for users without the
corresponding permission, and "Review Queue" / "Folder Amounts"
are hidden when not applicable.
No configuration changes are required after upgrading. Existing
permission grants continue to work; the gates above simply enforce
them where they previously weren't.
Performance Faster search for non-admin users
On large document collections, search for non-admin users could
take 20-30 seconds even for queries that returned only a handful
of results. The cause was the per-row permission check expanding
into a sequential scan of the entire document table instead of
being evaluated only on the matching candidates. Two changes:
- Search now computes the user's set of accessible folders
once per query via a new
fn_accessible_folder_ids
helper and filters by set membership, instead of calling the
per-folder permission check for every row. On a 21,500-document
dataset this turns a ~29s search into a sub-second one and scales
linearly with the matching result set rather than the table size.
- The highlighted result snippet is now generated only for the
documents actually shown on the current page (typically 50)
instead of for every document that matched the query.
The change is rule-for-rule equivalent to the previous permission
model: direct grants, group grants, folder-to-folder inheritance,
cabinet-to-folder inheritance, and permissions_inherited=FALSE
blocks all behave the same. No configuration changes required.
Fix OCR no longer silently drops pages
Previously, when OCR produced no text for a page (a blank scan or a
page Tesseract couldn't read), that page was dropped entirely and the
document was still marked fully processed — so a 300-page PDF
could end up with only 254 searchable pages and no indication
anything was missing. Now:
- Every page is recorded, including blank ones, so coverage gaps
are tracked instead of hidden.
- File Properties shows OCR coverage
(e.g. "254 / 300 pages (85%)") and a Partial badge when a
document didn't fully OCR.
- Right-click a document for Re-OCR Document (full
re-process) or Re-OCR Missing Pages, which retries
only the blank pages at a higher resolution — far cheaper than
re-processing the whole file.
v2026.05.25
2026-05-25
New Database consistency self-check
A new admin page (Administration → Consistency) runs four
complementary read-only health checks on the database, on a schedule
you configure, and surfaces the results in the admin UI.
- VACUUM ANALYZE per table — catches heap-tuple xmin/xmax inconsistencies (the class of corruption that can hide for days after a crash).
- pg_amcheck --heapallindexed — B-tree index integrity, including entries pointing at non-existent heap tuples.
- TOAST integrity via pg_dump — the gold-standard test for missing TOAST chunks (large-value storage). A successful dump means every row could be fully materialised.
- FK orphan scan — DocuMan-specific check across seven relationships (orphan pages, tags, notes, review-queue rows, etc.) that don't have CASCADE constraints.
Schedule it daily or weekly — weekly is recommended
(the TOAST scan is I/O-heavy on large databases). A "Run Check Now"
button is always available for ad-hoc checks. Each run records
pass/fail per check with summaries, viewable in a per-row Details
dialog. Optional email-on-failure target.
Fix Cross-cabinet folder move
Moving a folder to a different cabinet via right-click →
Move To… previously failed with a generic 400
error. The underlying SQL function referenced a column
(updated_by) that had never been added to the folders table.
This release adds the column, backfills historical rows from
created_by, and patches every folder-mutating function to
populate it consistently — completing the
created_by/updated_by/deleted_by audit
trio.
New PostgreSQL tuning admin page
A new Administration → PostgreSQL Tuning page
exposes the five memory and planner parameters that most affect
search and OCR throughput (shared_buffers,
effective_cache_size, work_mem,
maintenance_work_mem, random_page_cost).
The page shows the current value, a recommended value computed
from the host's RAM (with a 10 GB reserve for the OS and DocuMan's
own services), and an Apply button that runs
ALTER SYSTEM SET for each parameter and reloads
PostgreSQL. When the docman database role isn't a
superuser, the page returns the exact psql commands
for the operator to run as the postgres superuser
instead. The defaults that ship with the PostgreSQL installer
(128 MB shared_buffers, random_page_cost = 4.0)
are tuned for tiny databases on spinning disks — not for a
real DocuMan corpus.
Improvement Search speed on large databases
Searches for common terms on large databases (25 000+ documents,
1+ million pages) were taking 10+ seconds. The cause was an
OR clause that spanned two tables in the search
function: PostgreSQL can't combine GIN bitmaps from two different
relations, so it fell back to a single-pass plan that re-computed
a tsvector on every document row. Both search functions are
rewritten to gather candidate documents via a UNION
of single-table indexed lookups (each leg now uses its own GIN
index), then narrow to the candidate set, then pick the best
matching page per document for the snippet. The unused
substring-match legs are pruned from the plan entirely via
SET LOCAL plan_cache_mode = force_custom_plan.
On large corpora this turns multi-second searches into
sub-second — especially when combined with the new
PostgreSQL tuning recommendations above.