Skip to content

CI rehearsal only (do not merge) - #15

Open
michael-moffett wants to merge 8 commits into
mainfrom
pay-kit-89-m1-swift-runner-a1-next
Open

michael-moffett wants to merge 8 commits into
mainfrom
pay-kit-89-m1-swift-runner-a1-next

Conversation

@michael-moffett

Copy link
Copy Markdown
Member

Fork CI only. Do not merge.

michael-moffett and others added 2 commits October 3, 2026 08:03
…atrix

Add a Swift stdin/stdout runner over SolanaPayKit's protocol functions, plus `harness/protocol-runners/swift.json`, so the spawned-runner block runs Swift.

No mpp-protocol vector reaches the Swift SDK. Milestone 1 of the harness proposal puts Swift in the matrix.
@greptile-apps

greptile-apps Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

[High risk] Adds Swift protocol runner to CI and test harness.

This PR should not be merged while the previously reported Swift protocol-conformance failures remain.

Findings

  1. P1 Challenge description is lost ▶
  2. P1 Canonical credentials cannot be formatted ▶
  3. P2 Swift smoke coverage misses functionality ▶

Summary

The PR adds a Swift protocol runner, wires it into the harness and Swift CI, and updates the runner to ignore unknown challenge parameters.

  • The latest change replaces rejection of unknown challenge parameters with rejection of description alone and adds an extension-parameter test.

Reviews (4) · Last reviewed commit: "greptile.json: review on request only"

Comment on lines +66 to +74
"method": challenge.method,
"intent": challenge.intent,
"request": try decodeJSON(challenge.request),
]
if let expires = challenge.expires { result["expires"] = expires }
if let digest = challenge.digest { result["digest"] = digest }
if let opaque = challenge.opaque { result["opaque"] = try decodeJSON(opaque) }
return result
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Challenge description is lost

When challenge.parse receives a valid challenge with a description, such as the canonical full_challenge vector, the returned object omits it. The parsed result no longer matches the protocol object, so full conformance checks fail and callers cannot recover the description.

Comment on lines +83 to +97
try rejectUnknownKeys(payload, ["type", "transaction", "signature"], at: "payload.")
guard let request = challenge["request"] else { throw RunnerError(description: "missing challenge.request") }
let echo = try PaymentChallenge(
id: required(challenge, "id", at: "challenge."),
realm: required(challenge, "realm", at: "challenge."),
method: required(challenge, "method", at: "challenge."),
intent: required(challenge, "intent", at: "challenge."),
request: encodeJSON(request),
expires: string(challenge, "expires", at: "challenge."),
digest: string(challenge, "digest", at: "challenge."),
opaque: challenge["opaque"].map(encodeJSON)
).echo()
return PaymentCredential(
challenge: echo,
payload: try JSONDecoder().decode(CredentialPayload.self, from: JSONSerialization.data(withJSONObject: payload)),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Canonical credentials cannot be formatted

The canonical basic_credential format input has type: "transaction" and a signature, but no transaction field. This code decodes it with CredentialPayload, which requires transaction for that type, so credential.format returns an error instead of a header. The canonical hash-payload format case is also rejected by the new field allowlist.

Comment on lines +223 to 232
const allowlist = parseLanguageAllowlist(process.env.MPP_CONFORMANCE_LANGUAGES);
const runners = discoverProtocolRunners().filter(
(runner) => !allowlist || allowlist.has(runner.language),
);
for (const runner of runners) {
const known = KNOWN_RUNNER_DIVERGENCES[runner.language] ?? new Set<string>();
const known = KNOWN_RUNNER_DIVERGENCES[runner.language] ?? {};
describe(`mpp-protocol conformance (spawned ${runner.language} runner)`, () => {
const adapter = spawnedProtocolAdapter(runner);
for (const testCase of smokeCases) {
if (!caseRunsOnAdapter(testCase, runner.language)) continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Swift smoke coverage misses functionality

The Swift conformance job runs only the selected smoke cases: six confirm that operations remain unsupported, while the one conforming case parses a minimal challenge. It never checks the newly implemented credential.format operation or optional challenge fields. Regressions in those parts of the runner can therefore pass this job unnoticed.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment thread swift/Sources/mpp-protocol-runner/main.swift
michael-moffett and others added 2 commits October 3, 2026 16:59
…entChallenge cannot carry (description) and ignores extension params per spec
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant