Independent Operation and Maintenance Logs
Platform version: 2.00.091.
Operation logs and maintenance logs use independent platform APIs and management pages. They are no longer project-management data structures and must not be stored in device app_attrs. Project and device pages may retain entry points, but queries, saves, tags and attachments must use the independent log services without creating duplicate project storage.
Device association
Use the log's eui field when a device link is needed. A project log may link to the device representing the project. The platform permits an empty EUI; the business decides whether a link is required. Do not automatically bind the first listed device or put a device ID/project ID in eui.
Keep association-not-ready explicit. If the business requires a link, wait for that association before saving. Otherwise follow the verified API convention for an empty value. An empty device log list does not establish that the project or other devices have no logs.
API integration boundary
| Capability | Integration and verification |
|---|---|
| Query and save | Use each log type's independent API; query again after saving |
| Device association | Test linked and empty EUI cases, including the project representative device mapping |
| Tags | Maintain tags through log saves; use find-tags to list used tags and verify changes/removal |
| Attachments | Use the accompanying attachment APIs; verify upload, association, retrieval, deletion and permissions |
| Page entry points | Read the same platform log rather than storing a project copy |
Verified 18-endpoint contract
Release c08e93f5 corresponds to platform 2.00.091; package version remains 1.25.5. All endpoints use POST and business API header token: <TOKEN>. Both log types are limited to the token tenant, with no PUBLIC merge. Replace {kind} below with operation-log or maintenance-log.
| Method and path | Operation log operationId | Maintenance log operationId | Request / response |
|---|---|---|---|
| POST /thinklink/{kind}/find-page | operationLogFindPage | maintenanceLogFindPage | current/pageSize default 1/20; paginated result, total may be a decimal string |
| POST /thinklink/{kind}/batch-save-update | operationLogBatchSaveUpdate | maintenanceLogBatchSaveUpdate | dataList full-record UPSERT; {result:true,data:[{id}]} |
| POST /thinklink/{kind}/batch-delete-by-ids | operationLogBatchDeleteByIds | maintenanceLogBatchDeleteByIds | Required nonempty ids array; result includes rowCount/rows |
| POST /thinklink/{kind}/find-tags | operationLogFindTags | maintenanceLogFindTags | {}; {data:[{tag}]} |
| POST /thinklink/{kind}/attachment-quota | operationLogAttachmentQuota | maintenanceLogAttachmentQuota | {}; used_bytes/max_bytes |
| POST /thinklink/{kind}/attachment-list | operationLogAttachmentList | maintenanceLogAttachmentList | Required id; attachments and quota |
| POST /thinklink/{kind}/attachment-upload | operationLogAttachmentUpload | maintenanceLogAttachmentUpload | Required multipart id/file; optional attachment_id replacement and filename override; attachments and quota |
| POST /thinklink/{kind}/attachment-delete | operationLogAttachmentDelete | maintenanceLogAttachmentDelete | Required id/attachment_id; remaining attachments and quota |
| POST /thinklink/{kind}/attachment-download | operationLogAttachmentDownload | maintenanceLogAttachmentDownload | Required id/attachment_id; binary attachment |
Queries match id/eui/title and other fields exactly; tags must contain all requested tags. There is no project_id filter. Blank/null conditions are ignored, so an empty eui does not select unassociated logs. Default ordering is create_time DESC with no secondary key or consistent cross-page snapshot.
Saving is a full-record UPSERT, not a patch. Read and preserve existing fields before updating. Omitted title/content/remark/extra become null; omitted tags become []. Missing id generates a new ID; a supplied unknown ID also inserts. Tags are trimmed, deduplicated and cleared of blank values. Assign/remove tags through log saves; find-tags lists used tags, with no separate registry. Ordinary saves cannot modify attachments: new records start empty and updates preserve existing attachment metadata. Read back returned IDs; after a lost creation response, inspect correlation matches before retrying.
Create an operation log without a device link (<BASE_URL> is the business platform origin, not the MCP URL):
curl -X POST '<BASE_URL>/thinklink/operation-log/batch-save-update' \
-H 'token: <TOKEN>' -H 'Content-Type: application/json' \
--data '{"dataList":[{"eui":null,"title":"Inspection","content":"Example","tags":["inspection"]}]}'EUI may be omitted, null or blank; blank normalizes to null. The caller must verify actual device association. Obtain the returned log ID, check quota, then upload:
curl -X POST '<BASE_URL>/thinklink/operation-log/attachment-upload' \
-H 'token: <TOKEN>' \
--form 'id=<LOG_ID>' --form 'file=@<FILE_PATH>'The file limit and total per tenant per log type are both 50 MiB. Operation and maintenance attachments have separate quotas; this is not a per-record allowance. MinIO unavailable returns 503, missing logs/attachments 404, and exceeded limits 413. Replacement preserves attachment ID/create_time. Object cleanup after SQL commit can fail and leave an orphan; successful deletion does not prove object cleanup. Read back lists and quota after errors. MCP downloads also obey caller response-size limits and fail explicitly if oversized, without truncating.
Legacy projectLog* remains for compatibility and migration, not new storage. MCP discovery/preparation is not evidence of business log or attachment writes.
Historical migration and acceptance
Inventory old project tables, arrays, JSON and other sources. Record the business object, old record ID, target log type, target device EUI (or intentional absence), tags, attachments and callers. Keep an old-to-new record mapping and reconcile before retrying to avoid duplicate logs or attachments.
Back up first, then migrate logs, tags and attachment relations. Reconcile counts, business content, original timestamps and operators, device links, tag sets, attachment counts and actual readability. If a new API cannot preserve historical information, record and resolve the difference before switching; do not silently discard it. Reconcile new records created during migration as well.
Read the same record through the independent page and project/device entry points. Test creation, editing, device links, tags and attachments. Retire old storage and entry points only after historical and incremental reconciliation completes.
Report source adaptation, database migration, deployment, browser acceptance and MQTT integration separately. Independent logs do not imply automatic MQTT log delivery; mark untested stages as unverified.