mirror of
https://github.com/NomaDamas/k-skill.git
synced 2026-06-24 02:04:11 +00:00
Preserve toss empty-response auth-doctor contract
The prior review identified the empty portfolio/watchlist promotion rule as an upstream-contract dependency worth making explicit. Add regression coverage for the non-invalid auth doctor path and document that only parsed JSON with session.valid false promotes empty results to TossSessionExpiredError. Constraint: Scope is issue #126 / toss-securities only; public-restroom-nearby changes are excluded. Rejected: Treat any auth doctor output as session-expiry evidence | false positives would relabel valid empty portfolio/watchlist responses. Confidence: high Scope-risk: narrow Directive: Do not broaden empty-response promotion unless tossctl provides a stronger authenticated-empty-result contract. Tested: npm run lint --workspace toss-securities Tested: npm run test --workspace toss-securities (15/15) Tested: npm run ci Tested: Manual mock tossctl empty portfolio with session.valid true preserved [] Tested: Architect verification CLEAR Not-tested: Live Toss Securities account session behavior.
This commit is contained in:
parent
8243e231db
commit
925aed904e
2 changed files with 55 additions and 0 deletions
|
|
@ -40,6 +40,7 @@ npm install toss-securities
|
|||
세션 만료 관련:
|
||||
- `account summary` 등은 만료 시 에러를 던집니다.
|
||||
- 일부 커맨드(`portfolio positions`, `watchlist list`)는 upstream에서 빈 배열(`[]`)을 반환할 수 있어, 이 패키지는 기본적으로 `auth doctor`를 추가 확인해 만료를 `TossSessionExpiredError`로 승격합니다.
|
||||
- 이 승격은 `auth doctor`가 파싱 가능한 JSON을 반환하고 `session.valid === false`로 명시 확인될 때만 발생합니다. `auth doctor` 실패, 파싱 불가 출력, 또는 `session.valid !== false`는 세션 만료 판정으로 취급하지 않습니다.
|
||||
- 필요하면 `verifySessionOnEmpty: false`로 기존 빈 배열 동작을 유지할 수 있습니다.
|
||||
|
||||
대응되는 대표 CLI 는 `tossctl account summary --output json`, `tossctl quote get TSLA --output json`, `tossctl watchlist list --output json` 입니다.
|
||||
|
|
|
|||
|
|
@ -157,6 +157,33 @@ printf '{"ok":true}\\n'
|
|||
assert.deepEqual(passthrough.data, []);
|
||||
});
|
||||
|
||||
test("portfolio empty array is preserved when auth doctor does not confirm invalid session", async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "toss-securities-empty-valid-"));
|
||||
const binDir = path.join(tempDir, "bin");
|
||||
fs.mkdirSync(binDir, { recursive: true });
|
||||
|
||||
const script = `#!/bin/sh
|
||||
if [ "$3" = "portfolio" ] && [ "$4" = "positions" ]; then
|
||||
printf '[]\\n'
|
||||
exit 0
|
||||
fi
|
||||
if [ "$3" = "auth" ] && [ "$4" = "doctor" ]; then
|
||||
printf '{"session":{"valid":true}}\\n'
|
||||
exit 0
|
||||
fi
|
||||
printf '{"ok":true}\\n'
|
||||
`;
|
||||
|
||||
const binPath = path.join(binDir, "tossctl");
|
||||
fs.writeFileSync(binPath, script, { mode: 0o755 });
|
||||
|
||||
const env = { ...process.env, PATH: `${binDir}:${process.env.PATH || ""}` };
|
||||
|
||||
const result = await getPortfolioPositions({ env });
|
||||
|
||||
assert.deepEqual(result.data, []);
|
||||
});
|
||||
|
||||
test("portfolio blank stdout with invalid auth doctor is promoted to TossSessionExpiredError", async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "toss-securities-blank-"));
|
||||
const binDir = path.join(tempDir, "bin");
|
||||
|
|
@ -246,6 +273,33 @@ printf '{"ok":true}\\n'
|
|||
assert.deepEqual(passthrough.data, []);
|
||||
});
|
||||
|
||||
test("watchlist empty array is preserved when auth doctor does not confirm invalid session", async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "toss-securities-watchlist-empty-valid-"));
|
||||
const binDir = path.join(tempDir, "bin");
|
||||
fs.mkdirSync(binDir, { recursive: true });
|
||||
|
||||
const script = `#!/bin/sh
|
||||
if [ "$3" = "watchlist" ] && [ "$4" = "list" ]; then
|
||||
printf '[]\\n'
|
||||
exit 0
|
||||
fi
|
||||
if [ "$3" = "auth" ] && [ "$4" = "doctor" ]; then
|
||||
printf '{"session":{"valid":true}}\\n'
|
||||
exit 0
|
||||
fi
|
||||
printf '{"ok":true}\\n'
|
||||
`;
|
||||
|
||||
const binPath = path.join(binDir, "tossctl");
|
||||
fs.writeFileSync(binPath, script, { mode: 0o755 });
|
||||
|
||||
const env = { ...process.env, PATH: `${binDir}:${process.env.PATH || ""}` };
|
||||
|
||||
const result = await listWatchlist({ env });
|
||||
|
||||
assert.deepEqual(result.data, []);
|
||||
});
|
||||
|
||||
test("quote 403 includes upstream hint", async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "toss-securities-403-"));
|
||||
const binDir = path.join(tempDir, "bin");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue