The terminal ingestion path had never carried a single punch. It is fixed, promoted into a proper integration contract for the on-premise agent, monitored across every tenant, and — for the first time — something actually derives the attendance day from the punches.
A Terminal Could Never Authenticate, So Nothing Ever Arrived
The administration screen’s token box was discarded on every save, so the column stayed empty and the push endpoint then refused every terminal because a device with no token cannot push. The ingestion path shipped in the Shift Rotation and Rostering release had never carried a punch, and nothing reported it — a device that never pushed and a device whose token was never stored look identical.
A blank token on an edit now means leave it alone, never clear it: the dialog cannot prefill a write-only value, so taken literally, correcting a terminal’s location would have silently revoked its credential and surfaced hours later as a missing shift. The last-seen timestamp is also stamped in the plant’s zone; it had been recorded five and a half hours in the future on Indian sites, which suppressed the silent-device alarm for the length of a shift.
The Punch-Type Catalogue Had Never Been Seeded, on Any Tenant
Both ingestion paths resolve a punch to a row in a catalogue that no migration, command or fixture had ever populated — so on a fresh tenant every punch would have been rejected. It stayed invisible for as long as it existed because nothing had ever got far enough to reach the lookup. It is now seeded.
An unusable plant time zone also degraded silently to the system default. Every plant on two tenants was configured with a value that is not a real zone name. That fallback is right for a report, which should render rather than crash, and wrong for ingestion — a punch is a permanent fact, and storing one against a plant whose zone cannot be resolved means it can never afterwards be proved right. Ingestion now refuses by name.
Administrators: check that every plant’s time zone is a real zone name (for example Asia/Kolkata) before registering an agent.
Attendance Is Now Evaluated on a Schedule, and Silent Agents Are Reported
Nothing had ever triggered time evaluation. It was reachable only by a person pressing a button on a screen most tenants never open. Ingestion is deliberately inert — writing down a fact never derives a conclusion — so punches accumulated and no register, exception or overtime proposal was ever produced. A rolling three-day window is now re-derived on a schedule, per tenant.
A dead agent runs on a machine in the customer’s network that nobody here can log in to, and a monitoring screen only answers the question for whoever opens it — which nobody does on the day it matters. A daily sweep asks across every tenant and mails the result. A tenant that is behind on its upgrade is reported as such with its fix, rather than mailed as “agent down” twice a day until people stop reading.
A new Time › Integrations screen carries the silent-agent banner, status, credential rotation, the held-punch worklist, batch history and the employee mappings. On production the evaluation runs every six hours, which assumes nothing about a customer’s shift times and derives a conventional night shift within fifteen minutes of it ending.
An Integration Contract for the On-Premise Agent
The device-shaped push endpoint is promoted into an agent-shaped contract: a credential that is hashed rather than stored, a source transaction id with a database constraint behind it, a batch audit row, an employee mapping table, and a rejection that is kept rather than counted.
A rejection is a row carrying the whole original payload. That is what makes the agent’s checkpoint honest: it may move past a punch we refused only because we are holding it. Counting and discarding forces the agent either to stall on one bad row or to lose it. Held punches appear on a worklist with Replay, Ignore and Add mapping.
A punch travels as plant-local wall clock plus a named zone. A timestamp carrying its own offset is refused, and a declared zone that disagrees with the plant refuses the whole batch and stores nothing — converting would move every punch onto the wrong roster day and nothing downstream would report it. The zones are compared by resolved offset rather than by spelling, and probed twice in the year, so two zones that agree in one season and diverge in the other are caught now rather than in June.
A credential rotation keeps the previous secret alive for seven days, because revoking on rotation means the agent is dead from the button press until somebody has driven to the site. A repeated batch returns the stored result and re-processes nothing. An enrolment number gets reissued, so the employee mapping is date-effective — without that window a leaver’s punches silently become a new joiner’s, retrospectively.