ในบทความนี้
In this post
ตอนที่ 5 จากสิบสอง: แยกสิทธิ์ของแอปออกจากคะแนนโมเดล จำกัดให้ร่างข้อความเท่านั้น และทดสอบว่าการปฏิเสธหยุดงานต่อ
คำตัดสินและร่างข้อความเริ่มต้นเป็น mock ที่ผู้เขียนกำหนด ไม่ใช่ผล Jev จริง อ่านบทเรียนคู่กับ source, tests และแบบฝึกที่ลิงก์ไปยังรุ่นตรึงใน GitHub
เป้าหมายและสิ่งที่ต้องพร้อม
เตรียม Node22.18 ขึ้นไปกับ terminal clone companion จาก GitHub ตาม README หรือดาวน์โหลด ZIP ฉบับสมบูรณ์ แตกแล้วเข้า ai-core-functional-lab ไม่ต้อง npm install ใช้ API key หรือเรียกโมเดลผ่านเครือข่าย เวลาอ่านไม่รวมการลงมือประมาณ25–45นาที เก็บชุดอ้างอิงหนึ่งชุดและทำแบบฝึกในอีกสำเนา
ดาวน์โหลด companion ZIP · README / แผนบทเรียน
ตอนนี้เน้น src/policy.mjs โดย gate state บอกผลต่อชิ้นงานและทางไปต่อ ไม่มี state ใดส่งข้อความหรือแก้บัญชีจริง
จากโค้ดเดิมสู่ขอบเขตใหม่
authorization ถามว่าแอปนี้มีสิทธิ์ทำ action หรือไม่ ไม่ได้ถามว่าคำตอบโมเดลดูน่าเชื่อเท่าไร ตัวอย่างให้ draft_reply เท่านั้น การจำแนกอย่างมั่นใจว่างานมีประโยชน์ไม่ได้สร้างสิทธิ์ send_reply ให้เก็บด่านนี้เป็นฟังก์ชันโค้ดธรรมดา
policy มีสองชนิดของกฎ allowlist ของ action เป็นขอบแข็ง ส่วน threshold ความไม่แน่ใจเป็นพารามิเตอร์สอนที่ยังต้องยืนยันกับโดเมน การใส่ในไฟล์ config สะดวก แต่ไม่ได้ทำให้กฎถูกเอง
ตรวจสิทธิ์ก่อน generation และบนร่างที่คืนกลับ โมเดลหรือ adapter อาจเสนอ action ต่างจาก input ตัวอย่างไม่ทำ external action แม้ accept แล้ว ระบบจริงยังต้องมีขอบสิทธิ์ที่ผูกกับการยืนยันตัวตนต่างหาก
ลงมือทีละเจ็ดขั้น
ขั้นที่ 1
อ่าน authorizeInput โดยไม่ดู confidence เงื่อนไขมีเพียง action ที่ร้องขอ เขียนตารางความจริงของ draft_reply กับ string อื่นทั้งหมด
ขั้นที่ 2
รัน policy ของ V001 และ V004 ทั้งสองมีรูปแบบ input ถูก แต่มีเพียง V001 ที่ action ได้รับอนุญาต จึงแยกข้อมูลเสียรูปออกจากข้อมูลถูกที่ขอสิ่งต้องห้าม
ขั้นที่ 3
รัน pipeline ของ V004 ดู history ต้องหยุดที่ authorization ก่อน semantic input และ generation จำนวน provider calls เป็นศูนย์เป็นส่วนหนึ่งของ contract ที่ตรวจเห็นได้
ขั้นที่ 4
อ่าน authorizeDraft แล้วสมมติว่า generator คืน send_reply ด่าน action ปลายทางต้อง reject ไม่ใช่ยืมผลอนุมัติก่อนหน้าที่อนุมัติคนละ action
ขั้นที่ 5
ดู validatePolicy กับการตรวจ uncertainty band ถ้าขอบ no สูงกว่า yes จะตีความไม่สอดคล้อง config ที่เสียเป็นปัญหาของผู้ดูแล ไม่ใช่คำตอบโมเดลที่ควรเรียกซ่อม
ขั้นที่ 6
รัน test ที่ hard failure พร้อมค่า rubric เต็มทุกตัว ผลยังต้อง reject เมื่อ hardFailure เป็นจริง คะแนนเฉลี่ยคุณภาพซื้อสิทธิ์กลับคืนไม่ได้
ขั้นที่ 7
เขียนให้ชัดว่า accept อนุญาตเพียงชิ้นงานร่างในแบบฝึก อย่าใช้การไม่มี implementation ส่งข้อความเป็นหลักฐานว่าระบบจริงที่จะต่อในอนาคตบังคับขอบเดียวกันแน่นอน
ไฟล์และคำสั่งที่รันได้
เปิด source จริงและอ่าน dependencies ก่อนแก้ นี่คือโค้ดอ้างอิงที่รันได้ ไม่ใช่ SDK ชื่อ AI-Core ที่สมมติขึ้น ลิงก์ชี้ source รุ่นตรึงของ companion สาธารณะใน GitHub
src/policy.mjs · tests ของตอนนี้ · แบบฝึกตอนนี้
import {gate,probability} from './contracts.mjs';
export function validatePolicy(p) {
probability(p.choiceMin);probability(p.yesMin);probability(p.noMax);
if(p.noMax>=p.yesMin||p.noMax>=.5||p.yesMin<=.5) throw new Error('invalid uncertainty band');
for(const k of ['maxCalls','maxDrafts','timeoutMs'])
if(!Number.isSafeInteger(p[k])||p[k]<1) throw new Error('invalid '+k);
if(!Number.isSafeInteger(p.transportRetries)||p.transportRetries<0||p.transportRetries>2)
throw new Error('invalid retry bound');
if(typeof p.fallback!=='boolean') throw new Error('invalid fallback');
return p;
}
export function authorizeInput(input) {
return input.requestedAction==='draft_reply'?gate('accept'):gate('reject',['action_not_authorized']);
}
export function authorizeDraft(draft) {
return draft?.action==='draft_reply'?gate('accept'):gate('reject',['output_action_not_authorized']);
}
คำสั่งออฟไลน์:
node src/cli.mjs policy --case V001
node src/cli.mjs policy --case V004
node src/cli.mjs run --case V004
node --test --test-reporter=spec test/gates.test.mjs
ผลที่ควรได้และการตรวจ
policy ของ V001 คืน accept ส่วน V004 คืน reject ด้วย action_not_authorized เมื่อรันเต็ม V004 มี calls0 และ externalEffects0 ส่วน test hard failure ยัง reject แม้ rubric สูง
อ่าน reasons, history และทุก attempt ไม่ดูเพียง label สุดท้าย usage ที่ไม่ทราบต้องยังไม่ทราบ test สีเขียวแสดงเส้นทางโค้ดที่กำหนด ไม่ได้พิสูจน์ความปลอดภัยเชิงความหมายทุกกรณี
ตัวอย่างที่ต้องเข้าใจเมื่อไม่ผ่าน
ตรวจ action ต้นทางอย่างเดียวไม่พอ object ที่สร้างกลับมาอาจเปลี่ยน action ด่าน output จึงเป็น hard check อีกตัว ลบแล้วถือว่า regression แม้ fixture ปกติทุกเคสขอเพียงร่าง
แบบฝึกในสำเนาทดลอง
เพิ่ม table-driven test สำหรับ send_reply, refund และ delete_account ทุกตัวต้อง reject ก่อน provider อย่าเพิ่มสิทธิ์เหล่านี้เพื่อให้ตัวอย่างดูสำเร็จ
ทำตามไฟล์แบบฝึก เก็บต้นฉบับและคืนชุดอ้างอิงก่อนตอนถัดไป อย่าใช้ผล held-out เลือก threshold
ตรวจเมื่อผลไม่ตรง
หากคำขอไม่ผ่าน แยก action_not_authorized จาก unknown_input_field ตัวแรกเป็นการปฏิเสธตามสิทธิ์ ตัวหลังเป็นรูปแบบผิด การเปลี่ยน confidence threshold แก้ทั้งสองเรื่องไม่ได้
จุดตรวจถัดไป
ก่อนต่อ ให้บอกคุณสมบัติที่โค้ดตรวจได้แน่นอน คำตัดสินที่ผิดได้ state ที่หยุดงาน และหลักฐานที่ต้องมีก่อนปล่อยรุ่น
แหล่งอ้างอิงและรุ่น
เอกสารต้นทางและ companion source
ตรวจเอกสาร TypeSafe วันที่24ตุลาคม2026 บทเรียนตรึงคำขอข้อความที่ jev-1.14.0 และใช้ Choice/Noul ไม่ได้อ้างว่ามีเพียงความสามารถเหล่านี้ โค้ด REST ทางเลือกยังไม่ได้ลอง live ส่วน SDK0.7.0 มีเอกสารแต่แล็บนี้ไม่ต้องติดตั้ง
สิ่งที่ควรนำไปใช้ต่อ
- เงื่อนไขแน่นอนและสิทธิ์ยังอยู่ในโค้ด
- ด่านความหมายและคุณภาพผิดพลาดได้
- accept, reject, revise และ review มีทางไปต่อคนละแบบ
Part 5 of twelve. Encode permissions in deterministic policy; a confident answer never grants permission to send or modify data.
Default decisions and draft text are authored mocks, not live Jev results. Use the tutorial with the matching companion code, tests and exercise linked to a fixed GitHub version.
Outcome and prerequisites
Use Node22.18+ and a terminal. Clone the GitHub companion using its README, or download the complete ZIP, extract it and enter ai-core-functional-lab. No npm install, API key or network inference is needed. The reading-time label excludes about25–45 minutes of hands-on work. Keep one reference copy and make exercises in another.
Download companion ZIP · README / lesson map
This part focuses on src/policy.mjs. Expected gate states describe content and continuation; no state sends a message or changes a real account.
Old functions and the new boundary
Authorization answers may this application perform this action, not how plausible is the model’s answer. The sample permits draft_reply only. A confident classification of a request as useful does not create send_reply authority. Keep this as a small ordinary function.
The policy file contains two different kinds of rule. Action allowlists are hard boundaries; uncertainty thresholds are unvalidated teaching parameters that need domain validation. A configuration file is convenient storage, but it does not make either kind of rule correct by itself.
Check permissions both before generation and on the returned draft. A model or adapter can propose an action different from the input. This example never executes any external action even after acceptance; production authorization would need a separate authenticated boundary.
Seven practical steps
Step 1
Read authorizeInput without looking at confidence fields. Its entire input requirement is the requested action. Make a truth table for draft_reply and every other string.
Step 2
Run the policy command for V001 and V004. Both inputs are structurally valid, but only V001 has an allowed action. This separates invalid data from valid data asking for forbidden work.
Step 3
Run the full V004 pipeline and inspect the history. It should stop at authorization before semantic input or generation. Zero provider calls is part of the observable contract.
Step 4
Read authorizeDraft and imagine a generator returning send_reply. The downstream action check must reject that object rather than trusting the earlier authorization result for a different action.
Step 5
Inspect validatePolicy and its uncertainty-band checks. A no boundary above a yes boundary makes interpretation incoherent. Treat malformed application configuration as an operator problem, not a model answer to repair.
Step 6
Run the hard-failure quality test. Even perfect rubric values must yield reject when hardFailure is set. An average quality score cannot buy back permission.
Step 7
Document what accept permits: storage or display of a draft artifact within this exercise. Do not describe the absence of a sending implementation as proof that a future production integration will enforce the same boundary.
Files and runnable commands
Open the exact source and read its dependencies before editing. This is runnable reference code, not a fictional AI-Core SDK. The source links point to a fixed version of the public GitHub companion.
src/policy.mjs · Matching tests · This lesson’s exercise
import {gate,probability} from './contracts.mjs';
export function validatePolicy(p) {
probability(p.choiceMin);probability(p.yesMin);probability(p.noMax);
if(p.noMax>=p.yesMin||p.noMax>=.5||p.yesMin<=.5) throw new Error('invalid uncertainty band');
for(const k of ['maxCalls','maxDrafts','timeoutMs'])
if(!Number.isSafeInteger(p[k])||p[k]<1) throw new Error('invalid '+k);
if(!Number.isSafeInteger(p.transportRetries)||p.transportRetries<0||p.transportRetries>2)
throw new Error('invalid retry bound');
if(typeof p.fallback!=='boolean') throw new Error('invalid fallback');
return p;
}
export function authorizeInput(input) {
return input.requestedAction==='draft_reply'?gate('accept'):gate('reject',['action_not_authorized']);
}
export function authorizeDraft(draft) {
return draft?.action==='draft_reply'?gate('accept'):gate('reject',['output_action_not_authorized']);
}
Offline commands:
node src/cli.mjs policy --case V001
node src/cli.mjs policy --case V004
node src/cli.mjs run --case V004
node --test --test-reporter=spec test/gates.test.mjs
Expected output and verification
Policy V001 returns accept; V004 returns reject with action_not_authorized. Full V004 has calls0 and externalEffects0. The quality hard-failure test also rejects despite high rubric values.
Inspect reasons, history and every attempt rather than only the final label. Unknown usage must remain unknown. A green test demonstrates the specified code path, not universal semantic safety.
A failure to understand
Checking only the input action is insufficient: a generated object can change action. The output-side guard is a distinct hard check. Removing it is a regression even if every current happy-path fixture asks only for drafts.
Exercise in a disposable copy
Add a table-driven test for send_reply, refund and delete_account. All must reject before a provider runs. Do not add those actions to the allowlist just to make an example look successful.
Follow the matching exercise file, retain the original and restore the reference before the next chapter. Do not use held-out results to choose a threshold.
Troubleshooting
If a request unexpectedly fails, read action_not_authorized separately from unknown_input_field. One is a policy refusal, the other a shape violation. Changing confidence thresholds cannot repair either.
Next checkpoint
Before continuing, name the property that code checks exactly, the judgment that may be wrong, the state that stops work and the evidence needed before release.
← Previous lesson · Next lesson →
Sources and version notes
Primary documentation and companion source
Official TypeSafe docs checked2026-10-24. This curriculum pins text requests to jev-1.14.0 and uses Choice/Noul; it does not claim those exhaust Jev’s capabilities. Optional REST code is untested live. SDK0.7.0 is documented but unnecessary for this no-install lab.
Key takeaways
- Deterministic constraints and authorization stay in code.
- Semantic guards and quality judgments are fallible.
- Accept, reject, revise and review have distinct continuation rules.