mirror of
https://github.com/NomaDamas/k-skill.git
synced 2026-06-24 02:04:11 +00:00
Avoid leaking CJ contact details in published tracking examples
The first delivery-tracking draft exposed too much of the raw CJ event payload in the public examples. This follow-up keeps the examples useful for status checks while normalizing them to non-PII fields only, and locks that expectation in the docs regression suite so the raw field is not reintroduced. Constraint: Must preserve the verified official CJ flow while removing avoidable personal-contact leakage from the shipped examples Constraint: Follow-up had to stay docs-first and scoped to the existing feature/#4 PR branch Rejected: Keep raw CJ payload output and rely on users to ignore | published examples should not leak names/phone numbers unnecessarily Rejected: Drop CJ example detail entirely | loses practical verification value for the main carrier path Confidence: high Scope-risk: narrow Reversibility: clean Directive: Any future CJ example update must continue to avoid printing raw or other contact-bearing fields in public docs Tested: node --test scripts/skill-docs.test.js Tested: npm run ci Tested: python3 normalized CJ official endpoint verification for 1234567890 Tested: python3 우체국 follow-up verification for 1234567890123 Not-tested: Real non-placeholder customer waybills with different event shapes
This commit is contained in:
parent
3c6a7d2e51
commit
e257ab39a0
3 changed files with 46 additions and 4 deletions
|
|
@ -137,7 +137,6 @@ print(json.dumps({
|
|||
"status": status_map.get(latest.get("crgSt"), latest.get("scanNm") or "알수없음"),
|
||||
"timestamp": latest.get("dTime"),
|
||||
"location": latest.get("regBranNm"),
|
||||
"message": latest.get("crgNm"),
|
||||
"event_count": len(events),
|
||||
}, ensure_ascii=False, indent=2))
|
||||
PY
|
||||
|
|
@ -147,7 +146,7 @@ rm -f "$tmp_body" "$tmp_cookie" "$tmp_json"
|
|||
|
||||
추가 smoke test 로는 `000000000000` 도 사용할 수 있다.
|
||||
|
||||
CJ 응답은 `parcelResultMap.resultList` 가 비어 있어도 `parcelDetailResultMap.resultList` 쪽에 이벤트가 들어올 수 있으므로, 상세 이벤트 배열을 우선 본다.
|
||||
CJ 응답은 `parcelResultMap.resultList` 가 비어 있어도 `parcelDetailResultMap.resultList` 쪽에 이벤트가 들어올 수 있으므로, 상세 이벤트 배열을 우선 본다. 예시 출력은 `crgSt` / `scanNm` / `dTime` / `regBranNm` / 이벤트 수처럼 비식별 필드만 요약하고, 담당자 이름·연락처가 섞일 수 있는 `crgNm` 원문은 그대로 보여주지 않는다.
|
||||
|
||||
### 2. 우체국: official HTML flow
|
||||
|
||||
|
|
|
|||
|
|
@ -64,14 +64,38 @@ curl -sS -L -b "$tmp_cookie" \
|
|||
python3 - <<'PY' "$tmp_json"
|
||||
import json
|
||||
import sys
|
||||
|
||||
status_map = {
|
||||
"11": "상품인수",
|
||||
"21": "상품이동중",
|
||||
"41": "상품이동중",
|
||||
"42": "배송지도착",
|
||||
"44": "상품이동중",
|
||||
"82": "배송출발",
|
||||
"91": "배달완료",
|
||||
}
|
||||
|
||||
payload = json.load(open(sys.argv[1], encoding="utf-8"))
|
||||
print(json.dumps(payload["parcelDetailResultMap"]["resultList"][-1], ensure_ascii=False, indent=2))
|
||||
events = payload["parcelDetailResultMap"]["resultList"]
|
||||
if not events:
|
||||
raise SystemExit("조회 결과가 없습니다.")
|
||||
|
||||
latest = events[-1]
|
||||
print(json.dumps({
|
||||
"carrier": "cj",
|
||||
"invoice": payload["parcelDetailResultMap"]["paramInvcNo"],
|
||||
"status_code": latest.get("crgSt"),
|
||||
"status": status_map.get(latest.get("crgSt"), latest.get("scanNm") or "알수없음"),
|
||||
"timestamp": latest.get("dTime"),
|
||||
"location": latest.get("regBranNm"),
|
||||
"event_count": len(events),
|
||||
}, ensure_ascii=False, indent=2))
|
||||
PY
|
||||
|
||||
rm -f "$tmp_body" "$tmp_cookie" "$tmp_json"
|
||||
```
|
||||
|
||||
CJ는 JSON 응답이므로 `parcelDetailResultMap.resultList` 를 기준으로 상태를 읽는 편이 가장 안정적이다.
|
||||
CJ는 JSON 응답이므로 `parcelDetailResultMap.resultList` 를 기준으로 상태를 읽는 편이 가장 안정적이다. 문서 예시는 `crgSt` / `scanNm` / `dTime` / `regBranNm` / `event_count` 만 정리하고, 담당자 이름이나 휴대폰 번호가 포함될 수 있는 `crgNm` 원문은 그대로 출력하지 않는다.
|
||||
|
||||
## 우체국 예시
|
||||
|
||||
|
|
|
|||
|
|
@ -186,3 +186,22 @@ test("delivery-tracking skill documents official CJ and ePost flows with extensi
|
|||
assert.match(featureDoc, /JSON/);
|
||||
assert.match(featureDoc, /HTML/);
|
||||
});
|
||||
|
||||
test("delivery-tracking docs avoid raw CJ personal fields in published examples", () => {
|
||||
const skill = read(path.join("delivery-tracking", "SKILL.md"));
|
||||
const featureDoc = read(path.join("docs", "features", "delivery-tracking.md"));
|
||||
|
||||
assert.doesNotMatch(skill, /"message":\s*latest\.get\("crgNm"\)/);
|
||||
assert.doesNotMatch(
|
||||
featureDoc,
|
||||
/print\(json\.dumps\(payload\["parcelDetailResultMap"\]\["resultList"\]\[-1\],\s*ensure_ascii=False,\s*indent=2\)\)/,
|
||||
);
|
||||
|
||||
for (const doc of [skill, featureDoc]) {
|
||||
assert.match(doc, /"status_code":\s*latest\.get\("crgSt"\)/);
|
||||
assert.match(doc, /"status":\s*status_map\.get\(latest\.get\("crgSt"\),/);
|
||||
assert.match(doc, /"timestamp":\s*latest\.get\("dTime"\)/);
|
||||
assert.match(doc, /"location":\s*latest\.get\("regBranNm"\)/);
|
||||
assert.match(doc, /"event_count":\s*len\(events\)/);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue