fix(operations): preserve UTC markers in response timestamps
This commit is contained in:
@@ -31,12 +31,22 @@ public sealed class OperationsControllerTests
|
||||
Assert.IsType<NotFoundResult>((await controller.Get(otherId, default)).Result);
|
||||
|
||||
var cancelled = Assert.IsType<OkObjectResult>((await controller.Cancel(ownId, default)).Result);
|
||||
Assert.Equal(ownId, Assert.IsType<OperationDto>(cancelled.Value).Id);
|
||||
Assert.Equal(OperationStatuses.Cancelled, Assert.IsType<OperationDto>(cancelled.Value).Status);
|
||||
Assert.IsType<ConflictObjectResult>((await controller.Cancel(ownId, default)).Result);
|
||||
var retried = Assert.IsType<OkObjectResult>((await controller.Retry(ownId, default)).Result);
|
||||
Assert.Equal(ownId, Assert.IsType<OperationDto>(retried.Value).Id);
|
||||
Assert.Equal(OperationStatuses.Queued, Assert.IsType<OperationDto>(retried.Value).Status);
|
||||
Assert.IsType<ConflictObjectResult>((await controller.Retry(ownId, default)).Result);
|
||||
|
||||
await using var persistedDb = fixture.Context("user-1");
|
||||
var persisted = Assert.Single(await persistedDb.UserOperations.AsNoTracking().ToListAsync());
|
||||
Assert.Equal(ownId, persisted.Id);
|
||||
Assert.Equal(OperationStatuses.Queued, persisted.Status);
|
||||
Assert.Null(persisted.StartedAtUtc);
|
||||
Assert.Null(persisted.CompletedAtUtc);
|
||||
Assert.Null(persisted.CancellationRequestedAtUtc);
|
||||
|
||||
var serialized = JsonSerializer.Serialize(item);
|
||||
Assert.DoesNotContain("IdempotencyKey", serialized, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("LeaseToken", serialized, StringComparison.Ordinal);
|
||||
@@ -70,14 +80,28 @@ public sealed class OperationsControllerTests
|
||||
|
||||
await using var ownerDb = fixture.Context("user-1");
|
||||
var controller = fixture.NotificationsController(ownerDb);
|
||||
var operationBefore = JsonSerializer.Serialize(await ownerDb.UserOperations.AsNoTracking().SingleAsync());
|
||||
Assert.Single(Assert.IsAssignableFrom<IReadOnlyList<NotificationDto>>(
|
||||
Assert.IsType<OkObjectResult>((await controller.List(cancellationToken: default)).Result).Value));
|
||||
Assert.IsType<NoContentResult>(await controller.MarkRead(notificationId, default));
|
||||
var read = await ownerDb.UserNotifications.AsNoTracking().SingleAsync();
|
||||
Assert.Equal(notificationId, read.Id);
|
||||
Assert.NotNull(read.ReadAtUtc);
|
||||
Assert.IsType<NoContentResult>(await controller.MarkRead(notificationId, default));
|
||||
Assert.Equal(read.ReadAtUtc, (await ownerDb.UserNotifications.AsNoTracking().SingleAsync()).ReadAtUtc);
|
||||
Assert.IsType<NoContentResult>(await controller.Dismiss(notificationId, default));
|
||||
var dismissed = await ownerDb.UserNotifications.AsNoTracking().SingleAsync();
|
||||
Assert.NotNull(dismissed.DismissedAtUtc);
|
||||
Assert.IsType<NoContentResult>(await controller.Dismiss(notificationId, default));
|
||||
Assert.Empty(Assert.IsAssignableFrom<IReadOnlyList<NotificationDto>>(
|
||||
Assert.IsType<OkObjectResult>((await controller.List(cancellationToken: default)).Result).Value));
|
||||
await using var persistedDb = fixture.Context("user-1");
|
||||
var persisted = await persistedDb.UserNotifications.AsNoTracking().SingleAsync();
|
||||
Assert.Equal(notificationId, persisted.Id);
|
||||
Assert.Equal(read.CreatedAtUtc, persisted.CreatedAtUtc);
|
||||
Assert.Equal(read.ReadAtUtc, persisted.ReadAtUtc);
|
||||
Assert.Equal(dismissed.DismissedAtUtc, persisted.DismissedAtUtc);
|
||||
Assert.Equal(operationBefore, JsonSerializer.Serialize(await persistedDb.UserOperations.AsNoTracking().SingleAsync()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -95,6 +119,93 @@ public sealed class OperationsControllerTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Operation_and_notification_DTOs_preserve_all_UTC_instants_after_SQLite_roundtrips()
|
||||
{
|
||||
await using var fixture = await Fixture.CreateAsync();
|
||||
var created = new DateTime(2026, 10, 16, 8, 9, 10, DateTimeKind.Utc).AddTicks(1234567);
|
||||
var started = created.AddMinutes(1).AddTicks(2);
|
||||
var completed = created.AddMinutes(2).AddTicks(3);
|
||||
var deadline = created.AddMinutes(30).AddTicks(4);
|
||||
var cancellationRequested = created.AddSeconds(90).AddTicks(5);
|
||||
var noticeCreated = completed.AddTicks(6);
|
||||
var noticeRead = noticeCreated.AddMinutes(1).AddTicks(7);
|
||||
Guid operationId;
|
||||
var notificationId = Guid.NewGuid();
|
||||
await using (var seedDb = fixture.Context("user-1"))
|
||||
{
|
||||
var operation = (await fixture.Operations(seedDb).CreateAsync(Request("utc-transport"), default)).Operation;
|
||||
operationId = operation.Id;
|
||||
operation.Status = OperationStatuses.Failed;
|
||||
operation.CreatedAtUtc = created;
|
||||
operation.StartedAtUtc = started;
|
||||
operation.CompletedAtUtc = completed;
|
||||
operation.DeadlineAtUtc = deadline;
|
||||
operation.CancellationRequestedAtUtc = cancellationRequested;
|
||||
seedDb.UserNotifications.Add(new UserNotification
|
||||
{
|
||||
Id = notificationId, OwnerUserId = "user-1", OperationId = operationId,
|
||||
Kind = "operation_failed", Title = "Recorded operation", Message = "Stored UTC contract",
|
||||
CreatedAtUtc = noticeCreated, ReadAtUtc = noticeRead,
|
||||
});
|
||||
await seedDb.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await using var readDb = fixture.Context("user-1");
|
||||
var storedOperation = await readDb.UserOperations.AsNoTracking().SingleAsync();
|
||||
var storedNotification = await readDb.UserNotifications.AsNoTracking().SingleAsync();
|
||||
Assert.All(new[] { storedOperation.CreatedAtUtc, storedOperation.StartedAtUtc!.Value,
|
||||
storedOperation.CompletedAtUtc!.Value, storedOperation.DeadlineAtUtc!.Value,
|
||||
storedOperation.CancellationRequestedAtUtc!.Value, storedNotification.CreatedAtUtc,
|
||||
storedNotification.ReadAtUtc!.Value }, value => Assert.Equal(DateTimeKind.Unspecified, value.Kind));
|
||||
var operationBefore = JsonSerializer.Serialize(storedOperation);
|
||||
var notificationBefore = JsonSerializer.Serialize(storedNotification);
|
||||
|
||||
var operationController = fixture.OperationsController(readDb);
|
||||
var retrieved = Assert.IsType<OperationDto>(Assert.IsType<OkObjectResult>(
|
||||
(await operationController.Get(operationId, default)).Result).Value);
|
||||
var listed = Assert.Single(Assert.IsAssignableFrom<IReadOnlyList<OperationDto>>(
|
||||
Assert.IsType<OkObjectResult>((await operationController.List(cancellationToken: default)).Result).Value));
|
||||
var notification = Assert.Single(Assert.IsAssignableFrom<IReadOnlyList<NotificationDto>>(
|
||||
Assert.IsType<OkObjectResult>((await fixture.NotificationsController(readDb).List(cancellationToken: default)).Result).Value));
|
||||
Assert.Equal(operationId, retrieved.Id);
|
||||
Assert.Equal(retrieved, listed);
|
||||
Assert.Equal(notificationId, notification.Id);
|
||||
Assert.Equal(operationId, notification.OperationId);
|
||||
|
||||
// Web JSON serialization of controller DTOs; this fixture does not host HTTP.
|
||||
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
|
||||
foreach (var operation in new[] { retrieved, listed })
|
||||
{
|
||||
var json = JsonSerializer.SerializeToElement(operation, options);
|
||||
Assert.Equal(new[] { "id", "taskType", "status", "subjectType", "createdAtUtc", "startedAtUtc", "completedAtUtc",
|
||||
"deadlineAtUtc", "cancellationRequestedAtUtc", "progressStage", "progressPercent", "failureCategory", "canCancel", "canRetry" }.Order(),
|
||||
json.EnumerateObject().Select(property => property.Name).Order());
|
||||
AssertUtcJson(json, "createdAtUtc", created);
|
||||
AssertUtcJson(json, "startedAtUtc", started);
|
||||
AssertUtcJson(json, "completedAtUtc", completed);
|
||||
AssertUtcJson(json, "deadlineAtUtc", deadline);
|
||||
AssertUtcJson(json, "cancellationRequestedAtUtc", cancellationRequested);
|
||||
}
|
||||
var noticeJson = JsonSerializer.SerializeToElement(notification, options);
|
||||
Assert.Equal(new[] { "id", "operationId", "kind", "title", "message", "linkPath", "createdAtUtc", "readAtUtc" }.Order(),
|
||||
noticeJson.EnumerateObject().Select(property => property.Name).Order());
|
||||
AssertUtcJson(noticeJson, "createdAtUtc", noticeCreated);
|
||||
AssertUtcJson(noticeJson, "readAtUtc", noticeRead);
|
||||
|
||||
await using var verifyDb = fixture.Context("user-1");
|
||||
Assert.Equal(operationBefore, JsonSerializer.Serialize(await verifyDb.UserOperations.AsNoTracking().SingleAsync()));
|
||||
Assert.Equal(notificationBefore, JsonSerializer.Serialize(await verifyDb.UserNotifications.AsNoTracking().SingleAsync()));
|
||||
}
|
||||
|
||||
private static void AssertUtcJson(JsonElement json, string property, DateTime expected)
|
||||
{
|
||||
Assert.EndsWith("Z", json.GetProperty(property).GetString());
|
||||
var instant = json.GetProperty(property).GetDateTimeOffset();
|
||||
Assert.Equal(TimeSpan.Zero, instant.Offset);
|
||||
Assert.Equal(expected.Ticks, instant.UtcDateTime.Ticks);
|
||||
}
|
||||
|
||||
private static CreateUserOperation Request(string key) => new("synthetic-test", key, "authorized", "local-only", "job", "42");
|
||||
|
||||
private sealed class CurrentUser(string? userId) : ICurrentUserService
|
||||
|
||||
@@ -60,16 +60,17 @@ public sealed record OperationDto(
|
||||
bool CanCancel,
|
||||
bool CanRetry)
|
||||
{
|
||||
// SQLite drops DateTime.Kind; these fields retain their stored UTC ticks.
|
||||
public static OperationDto From(UserOperation operation) => new(
|
||||
operation.Id,
|
||||
operation.TaskType,
|
||||
operation.Status,
|
||||
operation.SubjectType,
|
||||
operation.CreatedAtUtc,
|
||||
operation.StartedAtUtc,
|
||||
operation.CompletedAtUtc,
|
||||
operation.DeadlineAtUtc,
|
||||
operation.CancellationRequestedAtUtc,
|
||||
DateTime.SpecifyKind(operation.CreatedAtUtc, DateTimeKind.Utc),
|
||||
operation.StartedAtUtc is { } started ? DateTime.SpecifyKind(started, DateTimeKind.Utc) : null,
|
||||
operation.CompletedAtUtc is { } completed ? DateTime.SpecifyKind(completed, DateTimeKind.Utc) : null,
|
||||
operation.DeadlineAtUtc is { } deadline ? DateTime.SpecifyKind(deadline, DateTimeKind.Utc) : null,
|
||||
operation.CancellationRequestedAtUtc is { } cancellation ? DateTime.SpecifyKind(cancellation, DateTimeKind.Utc) : null,
|
||||
operation.ProgressStage,
|
||||
operation.ProgressPercent,
|
||||
operation.FailureCategory,
|
||||
@@ -116,8 +117,8 @@ public sealed class NotificationsController(UserNotificationStore notifications)
|
||||
notification.Title,
|
||||
notification.Message,
|
||||
notification.LinkPath,
|
||||
notification.CreatedAtUtc,
|
||||
notification.ReadAtUtc);
|
||||
DateTime.SpecifyKind(notification.CreatedAtUtc, DateTimeKind.Utc),
|
||||
notification.ReadAtUtc is { } read ? DateTime.SpecifyKind(read, DateTimeKind.Utc) : null);
|
||||
}
|
||||
|
||||
public sealed record NotificationDto(
|
||||
|
||||
@@ -17,7 +17,7 @@ The entry commit is `b5319981ad3d1bd635daff861453d23c0de5320b` on `codex/ui-rede
|
||||
| [P7-06](p7-06/README.md) | Remaining Application forms and global correspondence | All three boundaries implemented CONDITIONAL GO: forms4c325/inboxa791 normally pushed; [compose](p7-06/COMPOSE.md) Compose affected52/5 and fresh backend25 PASS; native10+inbox8+ordinaryP2-D01=19 PASS on LFCrTZzDtX5hNBSRBj5Xx; app/browser TypeScript, lint and build PASS. Actual image review 47/47; all-enabled44scans0violations/330incompletes triaged, human/device/provider qualifications remain. +10front/+0suites,+10browser,+7backend derive739/94,301,1041 only; no integrated full-suite claim. Hygiene PASS and normal223dcf5 push directly verified11:03:15UTC;06Fdeferred/57groups32routes/main unchanged; P7-07 contract first next |
|
||||
| P7-06F | Deferred `followMode` reviewed composer | Optional separately reviewed mail slice; **DEFERRED** until mode→draft/review action and fallback are explicitly decided |
|
||||
| [P7-07](p7-07/README.md) | Documents owner-scoped index | Implemented local scope CONDITIONAL GO. Contract pushed `8e4db12`; [UI](p7-07/UI.md) final affected86/8, native8+CV4+ordinaryP2-D01, types/lint/build PASS. All18 final images reviewed; axe15 scans0 violations/101 retained incompletes. Original32 routes plus `/documents` =33. Hygiene PASS; publication blocked by the unreachable Git host, no live synchronization claim. Actual MariaDB/human/device/production qualifications remain |
|
||||
| P7-08 | Existing notifications and operations | Existing store and real destinations; new enabled producers require F20 recovery evidence; planned |
|
||||
| [P7-08](p7-08/README.md) | Existing notifications and operations | In progress: separate UTC transport repair4/4 plus73 consumers PASS; recent-notification candidate49/6 and type/lint/build gates PASS. Native/visual acceptance pending; Operations presentation remains. Existing store/routes only, no new enabled producers; F20 gate retained. Normal publication currently blocked by unreachable Git host |
|
||||
| P7-09 | Remaining Settings, Connections and data lifecycle | Existing independent save scopes and sensitive-action guards; planned |
|
||||
| P7-10 | Admin operational presentation | Existing distinct Users/Audit/System routes and server authorization; planned |
|
||||
| P7-11 | Remaining Analytics/error/empty/dialog integration | Inventory-confirmed residual presentation only; existing reports remain; planned |
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# P7-08 — Existing notifications and operations
|
||||
|
||||
**Status: separate UTC compatibility repair validated locally; recent/count presentation remains in progress after its 49-case GREEN candidate. Final UI/native/publication acceptance is pending.** This checkpoint migrates existing notification and operation interfaces under the [approved handoff](../../phase-6/p6-05/PHASE7_HANDOFF.md#migration-order-and-commit-boundaries) and [implementation plan](../../IMPLEMENTATION_PLAN.md). It preserves the existing stores, routes, permissions and operation lifecycle.
|
||||
|
||||
## Entry and publication qualification
|
||||
|
||||
[P7-07 local acceptance](../p7-07/README.md) and its [Documents interface report](../p7-07/UI.md) establish the preceding bounded work. Documents code is committed locally as `5a67ec3d3d5dc27298814b0a3f46540cb54ea3a3`; publication documentation is committed as `84350b71a67400cd62730e46bf05f06176bcd733`. Neither local commit is evidence of publication.
|
||||
|
||||
Two actual normal development pushes fail because the configured Git host cannot be reached on port 443. The latest attempt runs **2026-10-16 16:31:50.187856–16:32:11.434629 UTC**, exit **128**, retained under `.artifacts/phase7/p7-07/ui-publication-attempt-2/`. The earlier verified development remote at `8e4db12` is historical, not current live identity. Local `main` remains `27657f31131cd95d42f0e1290853ec9c9b3959a4`; this work does not push it. P7-07 publication remains blocked.
|
||||
|
||||
Independent P7-08 contract review, baseline checks and bounded safe work can proceed locally. The remote-access failure does not waive normal publication: each completed boundary still requires commit, push and fresh HEAD/remote verification. P7-12 cannot accept unpublished slices. After the **20:52 UTC** resumption, a fetch at **20:53:25–20:53:46** also exits 128 for the same connection failure; no new remote identity or execution during the usage pause is inferred.
|
||||
|
||||
## Two bounded presentation boundaries
|
||||
|
||||
| Boundary | Existing owners and intended preservation |
|
||||
|---|---|
|
||||
| Recent popover and shell unread count | `NotificationsPopover`, `notifications.ts`, `App` and `AppShell`; preserve recent-list limit 10, explicit read/dismiss, existing destination links, menu focus and bounded unread-count refresh |
|
||||
| Operations page | Existing `/operations` page and operation/notification stores; preserve list limits 50, current operation IDs, server-provided cancel/retry admission, notification read/dismiss and existing polling/recovery behavior |
|
||||
|
||||
Implement and validate the recent-popover/shell boundary before the separate Operations presentation boundary. Record the independently proven [UTC compatibility repair](UTC_TRANSPORT.md) in its own commit before presentation commits; this does not replace or reorder the two UI boundaries. Reuse the shared page/feedback/theme/i18n foundations. This scope adds no full `/notifications` application route, notification producer, result-data contract, scheduled-interview fact or task-completion feature. Existing `/api/notifications` remains its API owner. A meaningful full notification page or new enabled producer requires separate evidence; F20 recovery remains a prerequisite before new producers are enabled.
|
||||
|
||||
Read and dismiss affect notifications, not completion of the underlying work. Opening a notification uses its existing supported destination; no new result URL is fabricated. Cancel requests and Retry retain their server identities and eligibility rules, and cannot silently start duplicate work. Mail/provider/model capabilities remain within their existing qualifications.
|
||||
|
||||
## Recorded frontend baseline and RED
|
||||
|
||||
All times below are UTC on **2026-10-16**. Exact commands/reports remain under `.artifacts/phase7/current/unit/`; source observations remain under `.artifacts/phase7/p7-08/`.
|
||||
|
||||
| Observation | Actual result and source boundary |
|
||||
|---|---|
|
||||
| Existing affected consumers | **12 cases / 3 suites PASS**, **16:23:56.405875–16:24:02.029592**, `p708-entry-20261016T162356Z`: six popover, three Operations and three shell cases; no pending/todo cases |
|
||||
| Entry source observation | `entry-pre/source.json` captures 19 finite inputs before the baseline; `entry-after-observation.json`, observed **16:28:31.095687**, confirms all 19 unchanged after the baseline and before test edits. It does not infer identity across later test work |
|
||||
| First recent/count RED | **11 pass / 14 fail of 25**, **16:30:14.666388–16:30:25.644000**, `p708-recent-red-20261016T163014Z`; ordinary rendered-DOM/action failures, not compilation failure, with zero pending/todo cases. Nine inputs in `recent-red-pre/source.json` and `recent-red-post.json` match |
|
||||
| Expanded focus/GET RED | **12 pass / 17 fail of 29**, **16:35:03.956545–16:35:15.226833**; four new ordinary focus/GET cases add one passing and three failing observations. The 13 captured frontend inputs match. The broader 18-input snapshot includes a separate backend DTO edit after this command ended; do not claim all 18 were held |
|
||||
| First presentation candidate | **48/6 PASS**, **16:38:36.709407–16:38:50.647886**; affected popover, shell, Operations, navigation, quick-command and i18n cases, zero failed/pending/todo. All 18 candidate inputs are held before/after; subsequent additional GET/Retry focus coverage remains pending |
|
||||
| GET/Retry focus RED | **20 pass / 1 fail of 21**, **20:53:41.526191–20:53:48.271873**; the new ordinary popover case observes meaningful focus loss to BODY after GET recovery. All 18 captured inputs match before/after |
|
||||
| Latest presentation candidate | **49/6 PASS**, **20:54:23.214108–20:54:37.797995**; the added focus case and existing affected suites pass, zero failed/pending/todo. All 18 inputs in `retry-focus-green-pre/post` are held; actual native/visual evidence remains pending |
|
||||
|
||||
The first RED adds **13 ordinary cases**: ten popover and three shell cases. An existing shell count assertion is also strengthened; its failure does not represent an extra test. Four later focus/GET cases and the final Retry-focus case bring the candidate's additions to 18. The small recovery correction remembers the initiating Retry focus, waits for loading completion and preserves its original target while using the stable fallback. Retain every RED; a focused GREEN is not final interface acceptance.
|
||||
|
||||
The first candidate's app/browser TypeScript, lint and production build pass between **16:38:46 and 16:39:49 UTC**, with observed build identity **`33Og4QvWi-VvlxXRjUnvY`**. Old command/log receipts remain under `.artifacts/phase7/current/ui/attempts/`; that full static export was not separately copied. These are historical candidate gates, not native/visual or later-source acceptance.
|
||||
|
||||
Latest lint **20:54:33.381477–20:55:00.917580**, app TypeScript **20:55:00.919594–20:55:14.103408**, browser TypeScript **20:55:14.105415–20:55:20.863722** and build **20:55:20.865736–20:55:28.793130** all exit 0. Current build identity is **`-A-T31QuUMNqWVSxMqUu7`**. Frozen-source candidate checks do not close actual HTTP, native journeys, screenshots or final presentation acceptance.
|
||||
|
||||
## Findings and bounded repair requirements
|
||||
|
||||
| Observed source or regression finding | Required bounded behavior |
|
||||
|---|---|
|
||||
| Popover write protection uses React busy state alone | Reserve the operation synchronously before awaiting; repeated activation must not issue duplicate writes or competing Open actions |
|
||||
| Open awaits a read action whose failure is caught, then closes/navigates anyway | Preserve the visible notice/error and current context on failure; navigate only after the required action succeeds |
|
||||
| Action failures share a list-loading error/Retry presentation that hides rows | Keep known notices and distinguish action recovery from GET recovery; Retry must not replay a committed mutation |
|
||||
| Popover load depends on the translation callback and dates use the browser default locale | Language changes translate/reformat current data without another list read or lost state; use explicit English/Bokmål presentation |
|
||||
| Shell count starts at 0 and maps read failure to 0 | Distinguish known positive count, explicit known zero and unknown/unavailable count; do not announce a fabricated zero |
|
||||
| Shell interval/event reads have no ordering guard | A stale completion cannot overwrite the latest count or publish after unmount/account change; prove bounded single-flight/recovery behavior |
|
||||
|
||||
The notification trigger keeps its accessible name **“Notifications” / “Varsler”**. Count availability belongs in a localized `aria-describedby` description: known 3, known 0 and absent/unknown are distinct states. Preserve keyboard activation, close/focus restoration and the existing navigation/dirty guards. Latest candidate regressions include the GET/Retry focus repair; actual native evidence is still required.
|
||||
|
||||
Operations inspection records additional review targets: polling and list reads depend on translation callbacks; busy protection is state-only; two resources share a load/error path; task/status/failure values are displayed from raw identifiers. These are source findings to validate in the second boundary, not claims that an Operations migration or repair has executed.
|
||||
|
||||
## Separate UTC repair and native evidence plan
|
||||
|
||||
The [UTC repair report](UTC_TRANSPORT.md) and [portable results](evidence/utc-results.json) record ordinary **3 pass / 1 fail RED**, then **4/4 GREEN** and **73/73 related consumers**. Seven DTO projections now label stored UTC ticks without conversion, data writes or schema/auth/queue changes. This proves real SQLite plus direct-controller Web JSON serialization, **not hosted HTTP**; actual Program/cookie transport evidence remains pending. The repair is separate from presentation acceptance.
|
||||
|
||||
The guarded operation-only helper passes **29 self-checks**, **20:55:29.159474–20:55:29.645478**, using only its own temporary directory; its captured source remains held. This is not native/hosted evidence: actual CLI/schema execution and an existing cancel transition producing a notification remain pending. The Career seeder stays unchanged. Do not enable an operation handler, AI/model/provider worker or external grant to manufacture fixture content. Setup and actual domain-transition evidence must remain distinguishable from presentation fixtures.
|
||||
|
||||
Required native evidence includes real local-cookie read/dismiss/unread/reload and owner isolation, known/unknown count recovery, existing result/context links, failure/Retry/cancel, disconnect/reconnect recovery and no duplicate starts. Exercise keyboard/focus, bounded scroll containers, long English/Bokmål text and both themes across finite mobile/tablet/desktop samples. Record exact routes and writes, preserve every axe incomplete context and inspect actual images before drawing visual conclusions. No native, visual, axe or human acceptance is claimed at this entry checkpoint.
|
||||
|
||||
## Preservation, counts and remaining work
|
||||
|
||||
All **57 preservation groups remain 56 PARTIAL / C11 DEFERRED**; [preservation](../PRESERVATION.md) and [debt](../DEBT.md) remain binding. Keep **33 current routes**, comprising the original 32 plus Documents. Existing canonical Career Profile data, CV overrides/revisions, frozen packages, attachment bytes and provider/tenant boundaries remain protected. Notification read/dismiss must not alter those resource owners.
|
||||
|
||||
Entry inventory is **frontend 755/95, browser 312, backend 1,053** from P7-07. The one new UTC Fact derives backend **1,054**; 18 new frontend cases with no new suites derive **773/95**. The earlier 772/95 candidate count precedes the final Retry-focus case. These are inventories, not fresh integrated pass counts or final whole-checkpoint counts. Browser inventory stays 312 until native additions are executed and reconciled. Preserve all ordinary failures; no skip or expected-failure marker may conceal one. P7-12 owns the fresh integrated suite; its last full backend baseline remains 1,033.
|
||||
|
||||
Complete UTC repair hygiene and its separate commit, finish recent/count regressions and native/visual evidence, then validate the distinct Operations boundary. Each completed logical repair needs automated evidence, preservation reconciliation, hygiene, commit and normal push, with manual/native qualifications recorded honestly. Publication remains an actual network blocker; do not claim current synchronization from old refs.
|
||||
|
||||
Human screen-reader, real zoom, physical touch/software keyboard, production font/photo/print, actual MariaDB/provider execution and existing reliability debt remain qualified. P5-13 stays withheld with zero model qualification calls; followMode stays deferred. Production ingress, backup/restore, schema/configuration and tested rollback remain open release gates. **P7-08 acceptance: PENDING. Production: NO-GO; main not pushed. Phase 8: no implementation.**
|
||||
@@ -0,0 +1,41 @@
|
||||
# P7-08 — Operation and notification UTC transport
|
||||
|
||||
**Local SQLite/direct-controller scope: CONDITIONAL GO; hygiene PASS. Hosted HTTP/native acceptance, separate commit and normal push follow.** This bounded compatibility repair precedes the two [P7-08 presentation boundaries](README.md). [Portable UTC results](evidence/utc-results.json) retain exact commands, reports, source observations and qualifications.
|
||||
|
||||
## Demonstrated defect and minimal correction
|
||||
|
||||
Fresh SQLite materialization drops `DateTime.Kind` from stored UTC fields. The ordinary regression observes Web JSON `createdAtUtc` as **`2026-10-16T08:09:10.1234567`**, missing the required `Z`. A browser can therefore interpret the recorded UTC instant as local wall time.
|
||||
|
||||
The sole product change is in `JobTrackerApi/Controllers/OperationsController.cs`: seven DTO projections use `DateTime.SpecifyKind(value, DateTimeKind.Utc)`, preserving nullable values. The fields are five operation dates (`createdAtUtc`, `startedAtUtc`, `completedAtUtc`, `deadlineAtUtc`, `cancellationRequestedAtUtc`) and two notification dates (`createdAtUtc`, `readAtUtc`).
|
||||
|
||||
This labels the existing stored UTC ticks; it does not call `ToUniversalTime`, adjust instants or write rows. Routes, the exact 14-operation/8-notification public fields, ownership, authorization, queue/retry/cancel behavior and schema remain unchanged. No client-side timezone suffix is invented, and no new producer, handler, provider or model capability is enabled.
|
||||
|
||||
## Executed regression evidence
|
||||
|
||||
All times are UTC on **2026-10-16**. Raw `command.json`, `career.trx` and `career.log` files remain under `.artifacts/phase7/current/backend-career/`.
|
||||
|
||||
| Observation | Actual result |
|
||||
|---|---|
|
||||
| Ordinary UTC RED | **3 pass / 1 fail of 4**, **16:34:10.428105–16:34:31.629894**, `p708-utc-red-20261016T163410Z`. The new case fails on missing `Z` after fresh SQLite reload; four captured inputs match before/after |
|
||||
| UTC GREEN | **4/4 PASS**, **16:35:47.955889–16:35:57.322108**, `p708-utc-green-20261016T163547Z`, fresh Release compilation with `--no-restore`; zero failed/not-executed cases |
|
||||
| Related consumers | **73/73 PASS**, **16:36:14.129488–16:36:18.762446**, `p708-utc-consumers-20261016T163614Z`, `--no-build` against the compiled repair; zero failed/not-executed cases |
|
||||
|
||||
The new ordinary Fact uses distinct deterministic seven-digit fractional ticks for all seven dates, disposes the seeding context, then proves SQLite's materialized values have `Unspecified` kind. It invokes the actual controllers directly and serializes their DTOs with `JsonSerializerDefaults.Web`: Get/List agree, public field sets remain exact, every date has `Z`/zero offset/original ticks, and fresh persisted rows remain identical after reads.
|
||||
|
||||
The original three controller cases remain. Added persisted readback assertions strengthen cancel/retry and notification cases: the same operation ID/conflict rules and lifecycle resets persist; repeated notification read/dismiss retain timestamps and leave the associated operation unchanged. The 73 consumer cases cover operation stores, queue, StrategySnapshot, CV processing, ProfileCv, authorization posture and session middleware. These are affected subsets, not additional full-suite cases or deployed-service qualification.
|
||||
|
||||
## Source, binary and execution qualifications
|
||||
|
||||
`utc-green-post.json`, observed **16:39:08.852884**, confirms five backend source inputs held across the four contract and 73 consumer cases. Controller source SHA256 is `a2a38aee1d23c36f3cec617f1537f73d35639542087d4c1e5e7fb65f227440e2`; test source SHA256 is `06d6f91b70af4e1e98fe67246a76a9084d22a4050667295349a14c4d520c8e75`.
|
||||
|
||||
The API DLL SHA256 `e1d2c1bfc7ba4d9816d5d7b80503e79d2a647ad0ae2f4777e2703508fd32681c` and test DLL SHA256 `425d098903732802b5b304072c6f2e2f4479d74a56cf292d8c152544592dd99a` are actual **post-build/run observations**. They do not prove binary equality across a compilation that changes the product. Frontend work is outside these backend source holds. Resumption at **20:52 UTC** confirms the controller/test sources remain held; no execution is inferred during the usage pause.
|
||||
|
||||
This gate uses **real disk-backed SQLite and direct-controller Web JSON serialization**. It hosts no HTTP server or cookie middleware. Test names containing “API” do not change that boundary. Actual Program/local-cookie native journeys must still verify available UTC fields over HTTP and existing consumers; no hosted all-five-operation-date fixture is claimed. MariaDB, external provider/model execution, human/device/output and production release remain unverified.
|
||||
|
||||
## Preservation and publication
|
||||
|
||||
One new ordinary case derives backend inventory **1,054** from **1,053**; the existing three cases are strengthened and no case is skipped or removed. The last full backend run of **1,033** remains inherited until P7-12's integrated regression. Frontend/browser counts are reconciled separately from the presentation work.
|
||||
|
||||
All **57 PRES groups remain 56 PARTIAL / C11 DEFERRED**, and the original 32 routes plus Documents remain **33**. P5-13 stays withheld with zero model qualification calls; followMode is deferred. This correction does not establish full notification/operation UX acceptance or F20 recovery.
|
||||
|
||||
The [repair static checks](evidence/utc-static-checks.json) pass: secret scan, working/staged/phase whitespace, local documentation links, all 57 preservation groups and 33 current route patterns. Commit this compatibility change separately before presentation commits. P7-07 publication and normal development push remain blocked by the recorded port-443 connection failures; the fresh 20:53 UTC fetch also failed, so no current live remote equality is claimed. Actual commit/push outcomes will be recorded after execution. **Production: NO-GO; main unchanged. Phase 8: no implementation.**
|
||||
@@ -0,0 +1,814 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"checkpoint": "P7-08",
|
||||
"slice": "Separate operation/notification UTC transport repair",
|
||||
"recordedUtc": "2026-10-16T16:43:19.072716+00:00",
|
||||
"status": "LOCAL_CONTROLLER_SQLITE_SCOPE_CONDITIONAL_GO_HTTP_AND_PUSH_PENDING",
|
||||
"problem": "Fresh SQLite materialization loses DateTime.Kind; current Web JSON omits Z on fields defined as UTC, allowing browsers to interpret an instant as local time.",
|
||||
"change": "Label existing stored UTC ticks only in seven DTO projections with DateTime.SpecifyKind(...,Utc); preserve nullable values and every public/private boundary. No timezone conversion, storage/schema/provider/authorization/queue change.",
|
||||
"sources": [
|
||||
{
|
||||
"path": "JobTrackerApi/Controllers/OperationsController.cs",
|
||||
"bytes": 5810,
|
||||
"sha256": "a2a38aee1d23c36f3cec617f1537f73d35639542087d4c1e5e7fb65f227440e2",
|
||||
"canonicalLfSha256": "b1dacc6acf74dc3219bb7b5f13517d2e7edd7b9eb93297e8823dc1a90e0cbbd4"
|
||||
},
|
||||
{
|
||||
"path": "JobTrackerApi.Tests/OperationsControllerTests.cs",
|
||||
"bytes": 14599,
|
||||
"sha256": "06d6f91b70af4e1e98fe67246a76a9084d22a4050667295349a14c4d520c8e75",
|
||||
"canonicalLfSha256": "0b174f8f28ce98e1a7dacb121e80ca53e851bebced088f9388f7ce716af71800"
|
||||
}
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"name": "p708-utc-red-20261016T163410Z",
|
||||
"command": {
|
||||
"command": [
|
||||
"rtk",
|
||||
"proxy",
|
||||
"C:/Users/Connor/.dotnet/dotnet.exe",
|
||||
"test",
|
||||
"JobTrackerApi.Tests/JobTrackerApi.Tests.csproj",
|
||||
"--configuration",
|
||||
"Release",
|
||||
"--no-restore",
|
||||
"--filter",
|
||||
"FullyQualifiedName~OperationsControllerTests",
|
||||
"--logger",
|
||||
"trx;LogFileName=career.trx",
|
||||
"--results-directory",
|
||||
"E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\backend-career\\p708-utc-red-20261016T163410Z"
|
||||
],
|
||||
"startedUtc": "2026-10-16T16:34:10.428105+00:00",
|
||||
"finishedUtc": "2026-10-16T16:34:31.629894+00:00",
|
||||
"exitCode": 1,
|
||||
"logSha256": "c9552d40c81edcd63018c6059ea1ded8c43d4a741d852a2fd29c27f19922eeb2",
|
||||
"counts": {
|
||||
"total": 4,
|
||||
"passed": 3,
|
||||
"failed": 1,
|
||||
"notExecuted": 0
|
||||
},
|
||||
"resultSha256": "f4d3c2e06b9a4801ab0f7a77e03e2ef51ba6218ec1977ea576fa001059324e10"
|
||||
},
|
||||
"raw": [
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-red-20261016T163410Z/command.json",
|
||||
"bytes": 893,
|
||||
"sha256": "a98c302a0b0a7353b451878b56f1e01cedd873d3e2c9dd95682fa00260e39870"
|
||||
},
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-red-20261016T163410Z/career.trx",
|
||||
"bytes": 10389,
|
||||
"sha256": "f4d3c2e06b9a4801ab0f7a77e03e2ef51ba6218ec1977ea576fa001059324e10"
|
||||
},
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-red-20261016T163410Z/career.log",
|
||||
"bytes": 2431,
|
||||
"sha256": "c9552d40c81edcd63018c6059ea1ded8c43d4a741d852a2fd29c27f19922eeb2"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.OperationsControllerTests.Operation_and_notification_DTOs_preserve_all_UTC_instants_after_SQLite_roundtrips",
|
||||
"outcome": "Failed",
|
||||
"startUtc": "2026-10-16T18:34:31.1502359+02:00",
|
||||
"endUtc": "2026-10-16T18:34:31.1502360+02:00",
|
||||
"errors": [
|
||||
"Assert.EndsWith() Failure: String end does not match\r\nString: \"2026-10-16T08:09:10.1234567\"\r\nExpected end: \"Z\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.OperationsControllerTests.Operation_and_notification_endpoints_validate_bounds_and_require_local_auth",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:34:31.4264032+02:00",
|
||||
"endUtc": "2026-10-16T18:34:31.4264038+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.OperationsControllerTests.Operation_api_lists_mutates_and_hides_other_owner_records",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:34:30.9493918+02:00",
|
||||
"endUtc": "2026-10-16T18:34:30.9494046+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.OperationsControllerTests.Notification_api_is_owner_scoped_and_read_dismiss_are_idempotent",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:34:31.3444921+02:00",
|
||||
"endUtc": "2026-10-16T18:34:31.3444925+02:00",
|
||||
"errors": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "p708-utc-green-20261016T163547Z",
|
||||
"command": {
|
||||
"command": [
|
||||
"rtk",
|
||||
"proxy",
|
||||
"C:/Users/Connor/.dotnet/dotnet.exe",
|
||||
"test",
|
||||
"JobTrackerApi.Tests/JobTrackerApi.Tests.csproj",
|
||||
"--configuration",
|
||||
"Release",
|
||||
"--no-restore",
|
||||
"--filter",
|
||||
"FullyQualifiedName~OperationsControllerTests",
|
||||
"--logger",
|
||||
"trx;LogFileName=career.trx",
|
||||
"--results-directory",
|
||||
"E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\backend-career\\p708-utc-green-20261016T163547Z"
|
||||
],
|
||||
"startedUtc": "2026-10-16T16:35:47.955889+00:00",
|
||||
"finishedUtc": "2026-10-16T16:35:57.322108+00:00",
|
||||
"exitCode": 0,
|
||||
"logSha256": "323d6460a1a60842e42100728600fdb2388fb0d900b22f2c9f54d5063899a5e4",
|
||||
"counts": {
|
||||
"total": 4,
|
||||
"passed": 4,
|
||||
"failed": 0,
|
||||
"notExecuted": 0
|
||||
},
|
||||
"resultSha256": "e2335d90c22f18533632e962de9c102fbfd6780c21dfe0a897c60c233c48baee"
|
||||
},
|
||||
"raw": [
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-green-20261016T163547Z/command.json",
|
||||
"bytes": 895,
|
||||
"sha256": "730210eeb8a4130a5a53d6b94a4c083b8d7cb68744338d10065b98b6956f59d5"
|
||||
},
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-green-20261016T163547Z/career.trx",
|
||||
"bytes": 7364,
|
||||
"sha256": "e2335d90c22f18533632e962de9c102fbfd6780c21dfe0a897c60c233c48baee"
|
||||
},
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-green-20261016T163547Z/career.log",
|
||||
"bytes": 982,
|
||||
"sha256": "323d6460a1a60842e42100728600fdb2388fb0d900b22f2c9f54d5063899a5e4"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.OperationsControllerTests.Notification_api_is_owner_scoped_and_read_dismiss_are_idempotent",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:35:57.0595771+02:00",
|
||||
"endUtc": "2026-10-16T18:35:57.0595773+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.OperationsControllerTests.Operation_api_lists_mutates_and_hides_other_owner_records",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:35:56.6614171+02:00",
|
||||
"endUtc": "2026-10-16T18:35:56.6614328+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.OperationsControllerTests.Operation_and_notification_endpoints_validate_bounds_and_require_local_auth",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:35:57.1378130+02:00",
|
||||
"endUtc": "2026-10-16T18:35:57.1378132+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.OperationsControllerTests.Operation_and_notification_DTOs_preserve_all_UTC_instants_after_SQLite_roundtrips",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:35:56.8719219+02:00",
|
||||
"endUtc": "2026-10-16T18:35:56.8719228+02:00",
|
||||
"errors": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "p708-utc-consumers-20261016T163614Z",
|
||||
"command": {
|
||||
"command": [
|
||||
"rtk",
|
||||
"proxy",
|
||||
"C:/Users/Connor/.dotnet/dotnet.exe",
|
||||
"test",
|
||||
"JobTrackerApi.Tests/JobTrackerApi.Tests.csproj",
|
||||
"--configuration",
|
||||
"Release",
|
||||
"--no-build",
|
||||
"--filter",
|
||||
"FullyQualifiedName~UserOperationStoreTests|FullyQualifiedName~AiOperationQueueTests|FullyQualifiedName~StrategySnapshotOperationTests|FullyQualifiedName~CvProcessingOperationTests|FullyQualifiedName~ProfileCvControllerTests|FullyQualifiedName~ApiAuthorizationPostureTests|FullyQualifiedName~SessionContextMiddlewareTests",
|
||||
"--logger",
|
||||
"trx;LogFileName=career.trx",
|
||||
"--results-directory",
|
||||
"E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\backend-career\\p708-utc-consumers-20261016T163614Z"
|
||||
],
|
||||
"startedUtc": "2026-10-16T16:36:14.129488+00:00",
|
||||
"finishedUtc": "2026-10-16T16:36:18.762446+00:00",
|
||||
"exitCode": 0,
|
||||
"logSha256": "9020aa2db04a811442e20caa6f35dbfa6360b311f6120989e8b39f2cc0f6a711",
|
||||
"counts": {
|
||||
"total": 73,
|
||||
"passed": 73,
|
||||
"failed": 0,
|
||||
"notExecuted": 0
|
||||
},
|
||||
"resultSha256": "688ca8413035ac5b4209dff1a258f301ca7aabdb76efd0366af8cbde7d4e7293"
|
||||
},
|
||||
"raw": [
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-consumers-20261016T163614Z/command.json",
|
||||
"bytes": 1175,
|
||||
"sha256": "98ab5b12d422c1d3f6c646d7854a6b76c71fe06845db9c37397f1546cd9b4a30"
|
||||
},
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-consumers-20261016T163614Z/career.trx",
|
||||
"bytes": 105491,
|
||||
"sha256": "688ca8413035ac5b4209dff1a258f301ca7aabdb76efd0366af8cbde7d4e7293"
|
||||
},
|
||||
{
|
||||
"path": ".artifacts/phase7/current/backend-career/p708-utc-consumers-20261016T163614Z/career.log",
|
||||
"bytes": 615,
|
||||
"sha256": "9020aa2db04a811442e20caa6f35dbfa6360b311f6120989e8b39f2cc0f6a711"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Approved_fixture_regression_for_new_resume_docx_keeps_contact_and_role_core_fields_stable",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1102645+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1102648+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Running_cancellation_is_acknowledged_or_recovered_after_expiry",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.8052422+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.8052423+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ApiAuthorizationPostureTests.Admin_controllers_require_the_admin_role_not_merely_a_signed_in_user",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.7040043+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.7040045+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Rewrite_section_can_target_saved_job_context_and_whole_cv",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1090082+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1090083+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Parse_falls_back_to_section_parsing_when_ai_json_is_invalid",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1743047+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1743048+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Deadlines_and_input_bounds_fail_closed",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:16.9617850+02:00",
|
||||
"endUtc": "2026-10-16T18:36:16.9617851+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Rewrite_section_returns_ai_service_unavailable_detail_when_ai_health_is_unhealthy",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:16.7831663+02:00",
|
||||
"endUtc": "2026-10-16T18:36:16.7831667+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Upload_populates_structured_fields_from_flattened_cv_when_ai_json_is_invalid",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.5923912+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.5923913+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Approved_fixture_regression_for_cv_txt_keeps_core_fields_stable",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1552622+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1552628+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ApiAuthorizationPostureTests.Every_action_on_the_mixed_auth_controllers_declares_its_own_intent",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.7051261+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.7051263+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Parse_keeps_general_fallback_when_classifier_returns_nothing",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:16.9862009+02:00",
|
||||
"endUtc": "2026-10-16T18:36:16.9862012+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Concurrent_workers_cannot_claim_the_same_operation",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1442844+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1442845+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Parse_returns_structured_cv_and_persists_it",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.2878061+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.2878062+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Upload_accepts_markdown_cv_and_saves_text",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.2598197+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.2598202+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.CvProcessingOperationTests.Cancellation_before_claim_and_retry_keep_extraction_history_in_sync",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.5126652+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.5126653+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Admin_and_missing_sid_cannot_bypass_the_precondition",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6778635+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6778635+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Matching_context_preserves_the_authenticated_owner_for_downstream_code(method: \"DELETE\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6780707+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6780707+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ApiAuthorizationPostureTests.Every_controller_either_requires_authorization_or_is_listed_as_public",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.7030861+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.7030864+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Upload_waits_for_review_then_accept_merges_and_applies",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.4434905+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.4434910+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Normalized_markdown_parse_preserves_web_developer_bullets_and_skills",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.4841707+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.4841708+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.AiOperationQueueTests.Worker_resolves_owner_completes_once_and_creates_persistent_notification",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.6866704+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.6866705+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Missing_old_and_forged_contexts_never_reach_an_authenticated_mutation(method: \"POST\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6558172+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6558173+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Claim_filters_unknown_tasks_and_prioritises_interactive_work",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.6263534+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.6263535+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.GetRuns_returns_latest_extraction_runs",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:16.7335111+02:00",
|
||||
"endUtc": "2026-10-16T18:36:16.7335114+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Deterministic_parse_handles_real_estate_contact_summary_and_jobs",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:16.6709573+02:00",
|
||||
"endUtc": "2026-10-16T18:36:16.6709576+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.AiOperationQueueTests.Worker_classifies_retryable_failures_and_rechecks_live_entitlement",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.2540757+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.2540759+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Parse_uses_classifier_fallback_when_plain_text_has_no_real_sections",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.5243165+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.5243166+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Concurrent_duplicate_creation_returns_one_operation",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:18.3788342+02:00",
|
||||
"endUtc": "2026-10-16T18:36:18.3788343+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Stale_context_also_rejects_reads_but_unbound_bootstrap_is_allowed",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6792003+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6792003+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ApiAuthorizationPostureTests.The_user_owned_controllers_that_used_to_rely_on_the_fallback_policy_are_now_explicit",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.7000784+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.7000788+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Terminal_notification_is_single_and_owner_scoped_with_read_and_dismiss_state",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.3881173+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.3881173+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Missing_old_and_forged_contexts_never_reach_an_authenticated_mutation(method: \"PATCH\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6523210+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6523434+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Rewrite_section_returns_rewrite_empty_detail_when_ai_health_is_healthy",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.2969225+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.2969226+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Parse_uses_classifier_fallback_for_education_blocks_without_real_sections",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:16.9679892+02:00",
|
||||
"endUtc": "2026-10-16T18:36:16.9679894+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.AiOperationQueueTests.Worker_records_provider_metadata_for_generation_failures",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.3720136+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.3720139+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Reprocess_uses_latest_stored_artifact_and_creates_a_new_run",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.5588175+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.5588176+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.CvProcessingOperationTests.Upload_is_durable_idempotent_and_stops_at_review_gate",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.7004168+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.7004169+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Missing_old_and_forged_contexts_never_reach_an_authenticated_mutation(method: \"PUT\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6561354+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6561355+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Matching_context_preserves_the_authenticated_owner_for_downstream_code(method: \"PUT\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6779910+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6779910+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Background_processing_bypasses_the_http_user_filter_for_the_owned_run",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.2129823+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.2129824+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.StrategySnapshotOperationTests.Worker_persists_one_result_and_provider_metadata_then_GET_is_read_only",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.3880901+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.3880901+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.AiOperationQueueTests.Admission_is_pro_only_idempotent_bounded_and_contains_no_raw_payload",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.5956163+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.5956164+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.CvProcessingOperationTests.Deadline_before_claim_fails_the_dormant_extraction_run",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.2904359+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.2904360+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.AiOperationQueueTests.Free_and_ai_disabled_users_are_rejected_before_an_operation_is_created",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.5134878+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.5134879+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Upload_reconstructs_flattened_pdf_cv_before_save",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:16.9068885+02:00",
|
||||
"endUtc": "2026-10-16T18:36:16.9068887+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Notification_write_failure_rolls_back_terminal_operation_state",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:18.0879951+02:00",
|
||||
"endUtc": "2026-10-16T18:36:18.0879951+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ApiAuthorizationPostureTests.The_public_cv_controller_stays_anonymous",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6975430+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6975433+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Parse_uses_forced_ai_normalizer_output_when_enabled",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.3465717+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.3465719+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.StrategySnapshotOperationTests.Latest_operation_and_result_are_tenant_scoped",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.6242525+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.6242526+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Matching_context_preserves_the_authenticated_owner_for_downstream_code(method: \"GET\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6780497+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6780497+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.StrategySnapshotOperationTests.Invalid_provider_shape_is_retryable_and_does_not_publish_partial_output",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1910896+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1910899+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Multiple_headers_fail_closed",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6777872+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6777873+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Matching_context_preserves_the_authenticated_owner_for_downstream_code(method: \"PATCH\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6779596+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6779597+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Deterministic_parse_handles_flat_resume_contact_and_first_job",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1536570+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1536571+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.StrategySnapshotOperationTests.Producer_returns_202_and_duplicate_click_reuses_the_operation",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.5046328+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.5046329+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Structured_cv_normalization_separates_job_title_company_and_tasks",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.4521444+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.4521448+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.DiscardRun_leaves_profile_unchanged",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.4614189+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.4614190+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Expired_lease_retries_then_fails_after_bounded_attempts",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:18.2748744+02:00",
|
||||
"endUtc": "2026-10-16T18:36:18.2748744+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Upload_uses_ai_normalizer_fallback_when_flattened_text_stays_low_structure",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.4819296+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.4819296+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Approved_fixture_regression_for_coolfreecv_resume_keeps_summary_and_bullets_stable",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:16.6724045+02:00",
|
||||
"endUtc": "2026-10-16T18:36:16.6724046+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.CvProcessingOperationTests.Retryable_provider_failure_keeps_run_queued_and_records_provenance",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1229925+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1229927+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Binary_upload_does_not_fall_back_to_in_process_parsing",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1344801+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1344805+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Anonymous_authentication_flows_remain_available",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6779215+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6779216+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Structured_cv_normalization_hardens_contact_links_locations_and_dates",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1751111+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1751112+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Missing_old_and_forged_contexts_never_reach_an_authenticated_mutation(method: \"DELETE\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6774969+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6774970+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Unexpected_extraction_errors_are_not_exposed_to_users",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.5059355+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.5059356+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Failure_retry_completion_and_owner_guards_follow_the_state_machine",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:18.5867075+02:00",
|
||||
"endUtc": "2026-10-16T18:36:18.5867083+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Structured_cv_normalization_keeps_human_languages_and_drops_skill_noise",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.7970207+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.7970216+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Background_processing_rechecks_pro_after_queueing",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.2199833+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.2199834+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Upload_rejects_unsupported_extension",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1391065+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1391067+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.SessionContextMiddlewareTests.Matching_context_preserves_the_authenticated_owner_for_downstream_code(method: \"POST\")",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:15.6780232+02:00",
|
||||
"endUtc": "2026-10-16T18:36:15.6780232+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.UserOperationStoreTests.Create_is_idempotent_within_owner_and_isolated_between_owners",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.9443630+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.9443633+02:00",
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"name": "JobTrackerApi.Tests.ProfileCvControllerTests.Normalized_markdown_parse_preserves_real_estate_job_and_language_levels",
|
||||
"outcome": "Passed",
|
||||
"startUtc": "2026-10-16T18:36:17.1596299+02:00",
|
||||
"endUtc": "2026-10-16T18:36:17.1596302+02:00",
|
||||
"errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"reconciliation": {
|
||||
"redBefore": {
|
||||
"path": ".artifacts/phase7/p7-08/utc-red-pre/source.json",
|
||||
"bytes": 859,
|
||||
"sha256": "0e457e216e5456437c3ba526f473fd64c67dcc6301f8a78be89ebd3cb836bbb8"
|
||||
},
|
||||
"redAfter": {
|
||||
"path": ".artifacts/phase7/p7-08/utc-red-post.json",
|
||||
"bytes": 762,
|
||||
"sha256": "7b2f0d4bd7cc7d37e8a20d641099e3b542228cd3da6012ab054c9cde63c1313f"
|
||||
},
|
||||
"redInputsHeld": 4,
|
||||
"greenAndConsumers": {
|
||||
"path": ".artifacts/phase7/p7-08/utc-green-post.json",
|
||||
"bytes": 1844,
|
||||
"sha256": "1fd421aaa40c4c16d0e45512afa2d884f68fbaddcc33691ce18b3e2f0664b8bb"
|
||||
},
|
||||
"greenInputsHeld": 5,
|
||||
"binaries": [
|
||||
{
|
||||
"path": "JobTrackerApi/bin/Release/net9.0/JobTrackerApi.dll",
|
||||
"sha256": "e1d2c1bfc7ba4d9816d5d7b80503e79d2a647ad0ae2f4777e2703508fd32681c"
|
||||
},
|
||||
{
|
||||
"path": "JobTrackerApi.Tests/bin/Release/net9.0/JobTrackerApi.Tests.dll",
|
||||
"sha256": "425d098903732802b5b304072c6f2e2f4479d74a56cf292d8c152544592dd99a"
|
||||
}
|
||||
],
|
||||
"qualification": "Binary hashes are actual post-run observations following the Release test build; no unchanged-binary checksum across that build is invented. Frontend source changes are outside these backend gates."
|
||||
},
|
||||
"covered": [
|
||||
"Five operation dates and two notification dates use deterministic distinct seven-digit fractional ticks after disposal and fresh SQLite read contexts.",
|
||||
"Operation Get/List and notification List retain exact14/8 public fields; no private subject/result/provider/model/lease/idempotency exposure.",
|
||||
"Web-default JSON emits UTC Z and zero offset without changing original ticks. Complete persisted rows remain identical after DTO reads.",
|
||||
"Cancel/retry retain the same operation ID; cleared lifecycle fields and conflict rules remain. Repeated notice read/dismiss retain their original timestamps and do not mutate the associated task.",
|
||||
"73 related store/queue/strategy/CV-processing/ProfileCv/authorization/session cases pass against the compiled repair. These are subsets, not additions to the full suite."
|
||||
],
|
||||
"limits": [
|
||||
"Real disk-backed SQLite plus direct-controller Web JSON serialization; this gate does not host HTTP/cookie middleware.",
|
||||
"Planned actual Program/cookie native journeys must separately verify available UTC fields over HTTP and existing UI consumers. No all-five-date hosted fixture is claimed.",
|
||||
"No model/provider production equivalent runtime, human/device/output or release acceptance."
|
||||
],
|
||||
"inventory": {
|
||||
"previousBackend": 1053,
|
||||
"addedOrdinaryCases": 1,
|
||||
"currentDerivedBackend": 1054,
|
||||
"qualification": "Original three controller cases strengthened, one new ordinary case; no skips/removals. Last full backend1033 remains inherited untilP7-12."
|
||||
},
|
||||
"preservation": {
|
||||
"groups": 57,
|
||||
"status": "56 PARTIAL / C11 DEFERRED",
|
||||
"routes": "Original32 plus approvedDocuments route =33; unchanged by this repair.",
|
||||
"withheld": "P5-13 remains disabled/unqualified; no qualification/model calls.",
|
||||
"production": "NO-GO; main unchanged; Phase8 not started."
|
||||
},
|
||||
"publication": {
|
||||
"status": "PENDING_SEPARATE_LOCAL_COMMIT_AND_NORMAL_PUSH",
|
||||
"qualification": "P7-07 local5a67ec3 and receipt84350b7 normal pushes failed to connect to configured host443. No current live remote equality claim."
|
||||
},
|
||||
"hygiene": {
|
||||
"status": "PASS",
|
||||
"checkedUtc": "2026-10-16T21:00:05.989530+00:00",
|
||||
"path": "docs/redesign/phase-7/p7-08/evidence/utc-static-checks.json",
|
||||
"sha256": "82fb5dae47a23a421d314cbf45d934ae6dcf262b172d8d04cc0376499f0b60f9",
|
||||
"qualification": "535local links/21documents,57groups/33routes; staged scope remains two backend files plus their reports/status, with unrelated presentation work unstaged."
|
||||
},
|
||||
"hashPolicy": "UTF8 LF portable JSON; exact raw artifact hashes retained locally; canonical-LF source hashes qualify Git checkout conversion."
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"checkpoint": "p7-08",
|
||||
"status": "PASS",
|
||||
"checkedUtc": "2026-10-16T21:00:05.989530+00:00",
|
||||
"commands": [
|
||||
{
|
||||
"name": "secret-scan",
|
||||
"command": [
|
||||
"rtk",
|
||||
"proxy",
|
||||
"C:\\Users\\Connor\\AppData\\Local\\Programs\\Python\\Python312\\python.exe",
|
||||
"-X",
|
||||
"utf8",
|
||||
"scripts/supply-chain.py",
|
||||
"scan-secrets"
|
||||
],
|
||||
"startedUtc": "2026-10-16T21:00:02.440330+00:00",
|
||||
"finishedUtc": "2026-10-16T21:00:05.183098+00:00",
|
||||
"exitCode": 0,
|
||||
"log": ".artifacts/phase7/current/static/20261016T210002Z/secret-scan.log",
|
||||
"logSha256Raw": "c5a88d5ebdc042adba125c1eaacbe44f9f4a5c19898c0f195573c00d511aa28d"
|
||||
},
|
||||
{
|
||||
"name": "working-whitespace",
|
||||
"command": [
|
||||
"rtk",
|
||||
"proxy",
|
||||
"git",
|
||||
"diff",
|
||||
"--check"
|
||||
],
|
||||
"startedUtc": "2026-10-16T21:00:05.183601+00:00",
|
||||
"finishedUtc": "2026-10-16T21:00:05.294209+00:00",
|
||||
"exitCode": 0,
|
||||
"log": ".artifacts/phase7/current/static/20261016T210002Z/working-whitespace.log",
|
||||
"logSha256Raw": "e1e4bd0dff9863763b4ab8cfb5eb919afc9cf8858aaed942ffe02a9e204229dd"
|
||||
},
|
||||
{
|
||||
"name": "staged-whitespace",
|
||||
"command": [
|
||||
"rtk",
|
||||
"proxy",
|
||||
"git",
|
||||
"diff",
|
||||
"--cached",
|
||||
"--check"
|
||||
],
|
||||
"startedUtc": "2026-10-16T21:00:05.294209+00:00",
|
||||
"finishedUtc": "2026-10-16T21:00:05.386620+00:00",
|
||||
"exitCode": 0,
|
||||
"log": ".artifacts/phase7/current/static/20261016T210002Z/staged-whitespace.log",
|
||||
"logSha256Raw": "d2993bc68ad9a63f711c8f5473155e2ba00fdcd461220cc3849185f2f9ad93e6"
|
||||
},
|
||||
{
|
||||
"name": "phase7-whitespace",
|
||||
"command": [
|
||||
"rtk",
|
||||
"proxy",
|
||||
"git",
|
||||
"diff",
|
||||
"--check",
|
||||
"b5319981ad3d1bd635daff861453d23c0de5320b"
|
||||
],
|
||||
"startedUtc": "2026-10-16T21:00:05.387121+00:00",
|
||||
"finishedUtc": "2026-10-16T21:00:05.564209+00:00",
|
||||
"exitCode": 0,
|
||||
"log": ".artifacts/phase7/current/static/20261016T210002Z/phase7-whitespace.log",
|
||||
"logSha256Raw": "e1e4bd0dff9863763b4ab8cfb5eb919afc9cf8858aaed942ffe02a9e204229dd"
|
||||
}
|
||||
],
|
||||
"untrackedSecretScan": {
|
||||
"files": 2,
|
||||
"findings": 0
|
||||
},
|
||||
"documentation": {
|
||||
"files": 21,
|
||||
"relativeLinks": 535,
|
||||
"errors": []
|
||||
},
|
||||
"preservation": {
|
||||
"groups": 57,
|
||||
"statuses": {
|
||||
"PARTIAL": 56,
|
||||
"PASS": 0,
|
||||
"FAIL": 0,
|
||||
"DEFERRED": 1
|
||||
},
|
||||
"originalRoutesPreserved": true,
|
||||
"currentConcreteRoutes": 33
|
||||
},
|
||||
"production": {
|
||||
"main": "27657f31131cd95d42f0e1290853ec9c9b3959a4",
|
||||
"originMain": "27657f31131cd95d42f0e1290853ec9c9b3959a4",
|
||||
"status": "NO-GO",
|
||||
"qualification": "Local fetched refs; direct push observation recorded separately."
|
||||
},
|
||||
"hashPolicy": "Portable JSON UTF8 LF; raw log hashes measure exact saved bytes.",
|
||||
"limits": [
|
||||
"Pattern scanner skips binary and files over2MiB; not historical Git/production secrets.",
|
||||
"Local links check target existence, not URL/heading anchors.",
|
||||
"Static evidence is not runtime/manual/device/provider/production acceptance."
|
||||
]
|
||||
}
|
||||
@@ -91,7 +91,7 @@ Follow the approved [Phase 7 handoff](../redesign/phase-6/p6-05/PHASE7_HANDOFF.m
|
||||
- [x] P7-06 [remaining Application forms and global correspondence](../redesign/phase-7/p7-06/README.md): all three mandatoryboundaries implemented CONDITIONAL GO; forms4c325/inboxa791 pushed, compose final hygiene/normal push pending. Compose affected52/5 and fresh backend25 PASS; native10+inbox8+ordinaryP2-D01=19 PASS on LFCrTZzDtX5hNBSRBj5Xx; app/browser TypeScript, lint and build PASS. Actual image review 47/47; all-enabled44scans0violations/330incompletes triaged, human/device/provider qualifications remain. +10front/+0suites,+10browser,+7backend derive739/94,301,1041 only; no integrated full-suite claim. Preserve57/32,RD11/RD21/manual/provider/output/release debt,06Fdeferred/P513withheld/mainunchanged. NextP7-07backend contract first.
|
||||
- [ ] P7-06F optional reviewed followMode composer: retain deferral unless its required action/fallback decision is established.
|
||||
- [ ] P7-07 [owner-scoped Documents index](../redesign/phase-7/p7-07/README.md): implemented local scope CONDITIONAL GO; contract pushed8e4db12. UI final86/8 affected, native8+CV4+ordinaryP2-D01, app/browser types/lint/build PASS;18 actual final image reviews,15 axe scans0violations/101 retained incompletes. Original32 routes retained plus `/documents`; all57 statuses unchanged. Hygiene PASS; normal push blocked by the unreachable configured Git host. MariaDB/human/device/production qualifications remain open. Next P7-08 after checkpoint publication.
|
||||
- [ ] P7-08 existing notifications and operations.
|
||||
- [ ] P7-08 [existing notifications and operations](../redesign/phase-7/p7-08/README.md): UTC transport repair4/4 plus73 consumers PASS; recent-notification candidate49/6 and types/lint/build PASS. Native/visual acceptance and Operations presentation remain; no new producer/route/worker activation. Publication blocked by configured Git host connection failure.
|
||||
- [ ] P7-09 remaining Settings, Connections and data lifecycle presentation.
|
||||
- [ ] P7-10 Users, Audit and System administration presentation.
|
||||
- [ ] P7-11 residual Analytics/error/empty/dialog integration.
|
||||
|
||||
Reference in New Issue
Block a user