param([string]$DockerContext = "docker-prod") $ErrorActionPreference = "Stop" $coreContainer = "assistant-core-runtime-1" $commitContainer = "assistant-commit-runtime-1" $continuityContainer = "assistant-continuity-runtime-1" $receiverContainer = "assistant-notification-receiver-1" function Post-Json([string]$container, [string]$url, [object]$body) { $json = $body | ConvertTo-Json -Depth 10 -Compress $local = New-TemporaryFile $remote = "/tmp/domovoy-$([guid]::NewGuid().ToString('N')).json" try { [IO.File]::WriteAllText($local, $json, [Text.UTF8Encoding]::new($false)) docker --context $DockerContext cp $local "${container}:$remote" | Out-Null $result = docker --context $DockerContext exec $container wget -qO- --header "Content-Type: application/json" --post-file $remote $url if ($LASTEXITCODE -ne 0) { throw "POST $url failed" } return ($result -join "`n") } finally { docker --context $DockerContext exec --user root $container rm -f $remote 2>$null Remove-Item -LiteralPath $local -Force } } function Creator-Post([string]$url, [object]$body, [string]$token) { $json = $body | ConvertTo-Json -Depth 10 -Compress $local = New-TemporaryFile $remote = "/tmp/domovoy-$([guid]::NewGuid().ToString('N')).json" try { [IO.File]::WriteAllText($local, $json, [Text.UTF8Encoding]::new($false)) docker --context $DockerContext cp $local "${commitContainer}:$remote" | Out-Null $result = docker --context $DockerContext exec --env "CREATOR_TEST_SESSION=$token" $commitContainer sh -c 'auth=Authorization:\ Bearer\ $CREATOR_TEST_SESSION; IFS=; wget -qO- --header=Content-Type:application/json --header=$auth --post-file=$1 $2' sh $remote $url if ($LASTEXITCODE -ne 0) { throw "Creator POST $url failed" } return ($result -join "`n") } finally { docker --context $DockerContext exec --user root $commitContainer rm -f $remote 2>$null Remove-Item -LiteralPath $local -Force } } function Creator-Get([string]$url, [string]$token) { $result = docker --context $DockerContext exec --env "CREATOR_TEST_SESSION=$token" $commitContainer sh -c 'auth=Authorization:\ Bearer\ $CREATOR_TEST_SESSION; IFS=; wget -qO- --header=$auth $1' sh $url if ($LASTEXITCODE -ne 0) { throw "Creator GET $url failed" } return ($result -join "`n") } function Expect-CreatorStatus([string]$url, [object]$body, [string]$token, [int]$status) { $json = $body | ConvertTo-Json -Depth 10 -Compress $local = New-TemporaryFile $remote = "/tmp/domovoy-$([guid]::NewGuid().ToString('N')).json" try { [IO.File]::WriteAllText($local, $json, [Text.UTF8Encoding]::new($false)) docker --context $DockerContext cp $local "${commitContainer}:$remote" | Out-Null $previous = $ErrorActionPreference $ErrorActionPreference = "Continue" $result = (docker --context $DockerContext exec --env "CREATOR_TEST_SESSION=$token" $commitContainer sh -c 'auth=Authorization:\ Bearer\ $CREATOR_TEST_SESSION; IFS=; wget -S -O /dev/null --header=Content-Type:application/json --header=$auth --post-file=$1 $2' sh $remote $url 2>&1) -join "`n" $ErrorActionPreference = $previous if ($result -notmatch "HTTP/1\.[01] $status") { throw "Creator POST $url did not return $status" } } finally { docker --context $DockerContext exec --user root $commitContainer rm -f $remote 2>$null Remove-Item -LiteralPath $local -Force } } $sessionResponse = docker --context $DockerContext exec $coreContainer sh -c 'token=$CREATOR_BOOTSTRAP_TOKEN; if test x$CREATOR_BOOTSTRAP_TOKEN_FILE != x; then token=$(cat $CREATOR_BOOTSTRAP_TOKEN_FILE); fi; if test x$token = x; then exit 7; fi; header=Authorization:\ Bearer\ $token; IFS=; wget -qO- --header=$header --post-data={} http://localhost:8080/v1/creator/sessions' if ($LASTEXITCODE -ne 0) { throw "Creator session issuance failed" } $creatorSession = ($sessionResponse | ConvertFrom-Json).Token $suffix = [guid]::NewGuid().ToString("N") $scope = "domovoy-global-scope" $goal = "goal-creator-command-$suffix" $task = "task-creator-command-$suffix" $prospective = "prospective-creator-command-$suffix" Post-Json $coreContainer http://localhost:8080/v1/tasks @{TaskID=$task;GoalID=$goal;ScopeID=$scope;Revision=1} | Out-Null Post-Json $continuityContainer http://localhost:8081/v1/prospective-items @{ ID=$prospective;CommitmentID="commitment-$suffix";OwnerPrincipalID="domovoy-creator-principal" ScopeID=$scope;GoalID=$goal;TriggerAtUnixMillis=1800000000000;State="DELIVERED";Revision=1 } | Out-Null $command = @{ Target=@{TaskID=$task;GoalID=$goal;ScopeID=$scope;Revision=1} ProspectiveItemID=$prospective;ExpectedRevision=1;EvidenceRef="artifact://creator-command/$suffix" } Expect-CreatorStatus http://localhost:8082/v1/creator/continuity/satisfy-delivered $command "invalid" 401 $action = Creator-Post http://localhost:8082/v1/creator/continuity/satisfy-delivered $command $creatorSession | ConvertFrom-Json if ($action.State -ne "SUCCEEDED" -or -not $action.AuthorizedActionID -or -not $action.ActionIntentID -or -not $action.ActionAttemptID) { throw "Creator command response is incomplete" } $historyRaw = Creator-Get 'http://localhost:8082/v1/creator/authorized-actions?limit=50' $creatorSession $history = $historyRaw | ConvertFrom-Json $historyItem = @($history.Items | Where-Object { $_.AuthorizedActionID -eq $action.AuthorizedActionID }) if ($historyItem.Count -ne 1 -or $historyItem[0].ActionAttemptID -ne $action.ActionAttemptID -or $historyItem[0].State -ne 'SUCCEEDED') { throw "Creator action history does not contain the committed outcome" } if ($historyRaw -match 'EvidenceRef|GrantID') { throw "Creator action history exposed restricted envelope fields" } $updated = docker --context $DockerContext exec $continuityContainer wget -qO- "http://localhost:8081/v1/prospective-items/$prospective" | ConvertFrom-Json if ($updated.State -ne "SATISFIED" -or $updated.Revision -ne 2) { throw "Creator command did not satisfy item exactly once" } Expect-CreatorStatus http://localhost:8082/v1/creator/continuity/satisfy-delivered $command $creatorSession 409 Expect-CreatorStatus "http://localhost:8082/v1/creator/authorized-actions/$($action.AuthorizedActionID)/reconcile" @{} $creatorSession 409 $notificationProspective = "prospective-notification-$suffix" Post-Json $continuityContainer http://localhost:8081/v1/prospective-items @{ ID=$notificationProspective;CommitmentID="commitment-notification-$suffix";OwnerPrincipalID="domovoy-creator-principal" ScopeID=$scope;GoalID=$goal;TriggerAtUnixMillis=1800000000000;State="DELIVERED";Revision=1 } | Out-Null $notificationCommand = @{ Target=@{TaskID=$task;GoalID=$goal;ScopeID=$scope;Revision=1} ProspectiveItemID=$notificationProspective;ExpectedRevision=1;Confirm=$true } Expect-CreatorStatus http://localhost:8082/v1/creator/continuity/notify-delivered $notificationCommand "invalid" 401 $hostileNotification = $notificationCommand.Clone() $hostileNotification.URL = 'https://example.invalid' $hostileNotification.Body = 'arbitrary' Expect-CreatorStatus http://localhost:8082/v1/creator/continuity/notify-delivered $hostileNotification $creatorSession 400 $notificationAction = Creator-Post http://localhost:8082/v1/creator/continuity/notify-delivered $notificationCommand $creatorSession | ConvertFrom-Json if ($notificationAction.State -ne 'SUCCEEDED' -or -not $notificationAction.ActionIntentID) { throw 'Creator notification did not produce a successful receipt' } $notificationItem = docker --context $DockerContext exec $continuityContainer wget -qO- "http://localhost:8081/v1/prospective-items/$notificationProspective" | ConvertFrom-Json if ($notificationItem.State -ne 'DELIVERED' -or $notificationItem.Revision -ne 1) { throw 'Notification changed Continuity canonical state' } $receiptRaw = docker --context $DockerContext exec $receiverContainer sh -c 'token=$(cat /run/notification-reader/token); auth=Authorization:\ Bearer\ $token; IFS=; wget -qO- --header=$auth $1' sh "http://localhost:8085/delivery/v1/receipts/$($notificationAction.ActionIntentID)" if ($LASTEXITCODE -ne 0) { throw 'Notification receipt lookup failed' } $receipt = ($receiptRaw -join "`n") | ConvertFrom-Json if ($receipt.action_intent_id -ne $notificationAction.ActionIntentID -or $receipt.request_digest -notmatch '^[0-9a-f]{64}$') { throw 'Notification receipt evidence mismatch' } $notificationHistory = Creator-Get 'http://localhost:8082/v1/creator/authorized-actions?limit=50' $creatorSession | ConvertFrom-Json $notificationHistoryItem = @($notificationHistory.Items | Where-Object { $_.AuthorizedActionID -eq $notificationAction.AuthorizedActionID }) if ($notificationHistoryItem.Count -ne 1 -or $notificationHistoryItem[0].Operation -ne 'deliver-prospective-notification-v1' -or $notificationHistoryItem[0].State -ne 'SUCCEEDED') { throw 'Notification action history is incomplete' } Write-Output "Creator Commit command verification: PASS"