Skip to main content
Version: 1.1.0

feat-auto-attributes

New Features

Auto-attributes (Phase 1 — metadata-only)

Documents deposited by automatic services (Tower, future agents) now carry autoAttributes — structured metadata separate from manual user attributes. Smart lists ("Listes Automatiques") filter documents dynamically by attribute codes.

Reference documentation: docs/auto-attributes.md — folder filters, configuration model, platform API, dashboard setup. Update this doc when behaviour changes.

Schema changes:

  • documents.autoAttributes[] — new field {code, value}[], separate from documents.attributes[] (manual, unchanged)
  • companies.folders[].type'manual' | 'auto' (default 'manual')
  • companies.folders[].targetAttributeCodes[] — OR filter by code (any value)
  • companies.folders[].targetAutoAttributes[] — AND filter by {code, value} pairs
  • companies.folders[].displayedCodes[] — codes displayed per document in list view
  • attributes.code? — optional stable identifier for global attributes (companyRef: null)
  • agent_codes — new collection: agentName, allowedAttributeRefs[] (resolved from global catalogue)
  • auto_folder_templates — global smart-list templates cloned into company folders
  • apitokens.agent? — optional field linking an API token to a registered agent (managed via Retool)

API changes:

  • POST /documents — universal ingestion endpoint. Supports manual (attributes) and auto (autoAttributes) metadata. Bearer auth with optional Bcyip-Agent / Bcyip-Version / Bcyip-Platform headers. Strict validation against agent catalogue. Technical codes bcyip:agent and bcyip:agent-version auto-injected (not configurable on agents).
  • GET /documents — response extended with top-level autoAttributes: AutoAttributesCount[] and per-document autoAttributes[]
  • GET /documents — supports X-Mock: true header for front-first development
  • GET/POST/PATCH/DELETE /platform/agents — ingestion agents; body uses allowedCodes[] (catalogue codes, resolved to refs server-side)
  • GET/POST/PATCH/DELETE /platform/auto-attribute-codes — global auto code catalogue
  • GET/POST/PATCH/DELETE /platform/folder-templates — smart-list templates
  • GET/POST/PATCH/PUT /platform/companies/:id/* — cross-company ops (folders, attributes, label overrides) via X-Platform-Admin-Token
  • GET /platform/companies/:id/users/agents — per-user agents runtime map for ops dashboard

Auto-attribute codes:

  • Cross-cutting: source-type, source-name
  • Domain namespaces: git_repo, git_commit, git_branch, git_tag, ftp_source-path (_ separator; : reserved for bcyip:*)
  • Technical codes with bcyip: prefix — bcyip:agent, bcyip:agent-version (server-injected only)
  • Ingestion normalizes legacy bcyip-agent / unprefixed business bcyip:* during transition

User agent runtime:

  • users.agents — map keyed by agent name (iptower, ipmagicbox, …); neo updates on auto deposits
  • users.agent — legacy IP Magic Box field; backend still updates for dashboard GET /api/admin/users

Resolver:

  • FolderV0.TOWER — union Tower v1 (tags: bcyip-tower) + any agent deposit (bcyip:agent in autoAttributes, any value)
  • hasMultipleDocsTypes / GET /documents/should-display-folders — same isTower detection for Magic Box v0 tab bar (IP MagicBox / IP Tower)
  • Custom auto folders — dynamic filter via targetAutoAttributes or targetAttributeCodes (see reference doc)

Catalogue LOV (value labels):

  • Global auto codes support lov: [{ value, label }] (legacy string[] normalized on read)
  • allowExtraValues / allowMultipleValues exposed on platform CRUD (default allowExtraValues: true for auto)
  • GET /documents adds optional valueLabel on autoAttributes[] and filter value counts — additive, current IP Magic Box ignores it
  • GET /platform/auto-attribute-codes returns lov + lovValues (canonical strings for backward compat)
  • Ingestion never rejects values outside lov (manual or auto)

Bootstrap: global catalogue and agents are managed via /platform/auto-attribute-codes and /platform/agents (no seed scripts in repo).

Planned (not in this release): GET /platform/auto-attribute-codes/:code/observed-values — distinct deposited values per code for the ops label editor (see reference doc).

Agent ingest with legacy file upload (n8n / Airtable)

Goal: Let external automation upload a binary via the legacy files API, then create the neo document with autoAttributes in a second call — same pattern as Tower without coupling upload to documentId.

Solution: POST /documents accepts optional fileId (validated remotefiles row: same hash, same job, not already linked). Pipeline uses fileSize from the linked file when omitted.

Features:

  • Two-step flow: POST /api/files/upload/POST /api/v2/documents with hash, fileId, autoAttributes, agent token + Bcyip-Agent
  • OpenAPI documents fileId on the ingest body

Files Modified:

  • src/domains/document/document.controller.ts — optional fileId on ingest DTO
  • src/domains/document/document.service.tsresolveLinkedRemoteFile, link on create
  • src/domains/document/templates/documents.tsfileSize fallback from fileId.size

🐛 Bug Fixes

Goal: Retrying the same hash + jobRef (e.g. n8n replay) must not fail when fileId is sent again or when new autoAttributes arrive on retry.

Solution: On idempotent match, merge autoAttributes by code (incoming wins), set fileId only when absent, leave manual fields untouched.

Files Modified:

  • src/domains/document/document.service.tsapplyIdempotentDocumentUpdates

Automatic hall includes all agent deposits (not only iptower)

Goal: Documents deposited by any registered agent (n8n, future agents) must appear in folder=tower and trigger the Magic Box v0 tab bar when mixed with manual docs.

Solution: Match any bcyip:agent in autoAttributes (not only value: iptower) in buildDocumentFolderFilter and documentsTypeTemplate / isTower.

Files Modified:

  • src/domains/document/templates/documents.tsFolderV0.TOWER filter
  • src/domains/document/templates/initialValues.tsisTower aggregation
  • src/domains/document/document.service.tshasMultipleDocsTypes comment
  • docs/auto-attributes.md — folder filter, v0/v1 UI mapping, fileId + idempotent ingest

Improvements

Tower code naming alignment (docs + OpenAPI examples)

Goal: Keep neo documentation, release notes, and Scalar mock responses aligned with Tower v2 deposit codes (git_*, ftp_source-path) after dropping legacy ref / sha.

Solution: Update the canonical guide, platform agent Swagger examples, and GET /documents mock payload so ops and front devs see the same vocabulary as production deposits.

Files Modified:

  • docs/auto-attributes.md — taxonomy, folder filter examples, Tower codes table
  • .unreleased/feat-auto-attributes.md — code list in fragment
  • src/domains/document/document.controller.tsMOCK_RESPONSE auto-attribute examples
  • src/domains/platform/agents/agents.types.tsallowedCodes OpenAPI examples