Cleaning up test data on a live project¶
Written after an audit left artifacts on SA Test IFC. The rule this encodes: never invent a
delete path against production. If a supported one does not exist, build it in code, test it, ship
it, and then use it — which is how the sensor and element-progress deletes below came to exist.
What has a supported delete path¶
| Artifact | How |
|---|---|
| Clash suppression rule | Clash ownership settings → the rule's remove button |
| OAuth application | Workspace settings › OAuth apps → delete (revokes its grants and tokens too) |
| Schedule / programme | Standards & 4D › Schedule → select it → Delete programme (admins). Takes its tasks, dependencies, links and costs; audited as schedule.deleted |
| Sensor threshold | Assets & O&M › Sensors → open the sensor → remove the threshold |
| Sensor (device) | Assets & O&M › Sensors → the row's delete action. Removes readings + thresholds; keeps anomalies it raised |
| Element progress override | Viewer → select the element → Clear override. Restores the derived figure |
| Schedule task link | Standards & 4D › Schedule → a task's link panel → remove |
| Sheet markup | Sheets → the markup list beside the sheet → delete |
What has no delete path, and why¶
- Sensor readings on their own. They are only removable with their device. A per-reading delete would be a way to quietly edit history on a monitored asset.
- Anomalies. They have an open/ack/dismissed lifecycle instead. An anomaly is a record that something happened; dismissing it is the honest operation, deleting it is not.
- Audit log entries. Never deletable, by design.
Doing it over the API¶
Every delete above is a plain DELETE with a bearer token. One trap worth knowing: the app's own
api() helper omits Content-Type when there is no body, and the server rejects a JSON content-type
with an empty body. Sending Content-Type: application/json on a bodyless DELETE therefore returns
400 Body cannot be empty when content-type is set to 'application/json'
which looks like a broken route and is not. Omit the header.
Before you start¶
Confirm the artifacts are yours. GET the collection first and match on the name or external id you
created — an audit that deletes a customer's sensor because it looked like test data is a far worse
outcome than leaving a stray row behind.