2026-07-27 00:18:42 +08:00
import fs from 'node:fs' ;
import path from 'node:path' ;
2026-07-27 09:56:33 +08:00
import vm from 'node:vm' ;
import ts from 'typescript' ;
2026-07-27 09:44:08 +08:00
const contracts = [
2026-07-27 09:56:33 +08:00
{
"domain" : "gas" ,
"name" : "gas_basic" ,
"resource" : "/gas/gas_basic" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "code" ,
"required" : true
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "credit_code" ,
"required" : false
} ,
{
"key" : "principal" ,
"required" : false
} ,
{
"key" : "address" ,
"required" : false
} ,
{
"key" : "longitude" ,
"required" : false
} ,
{
"key" : "latitude" ,
"required" : false
}
]
} ,
{
"domain" : "gas" ,
"name" : "gas_account" ,
"resource" : "/gas/gas_account" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "username" ,
"required" : true
} ,
{
"key" : "password" ,
"required" : true
} ,
{
"key" : "display_name" ,
"required" : false
} ,
{
"key" : "role_code" ,
"required" : false
} ,
{
"key" : "gas_basic_identity" ,
"required" : true
}
]
} ,
{
"domain" : "delivery" ,
"name" : "delivery_basic" ,
"resource" : "/delivery/delivery_basic" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "delivery_code" ,
"required" : true
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "gas_basic_identity" ,
"required" : false
} ,
{
"key" : "principal" ,
"required" : false
} ,
{
"key" : "address" ,
"required" : false
}
]
} ,
{
"domain" : "delivery" ,
"name" : "delivery_account" ,
"resource" : "/delivery/delivery_account" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "username" ,
"required" : true
} ,
{
"key" : "password" ,
"required" : true
} ,
{
"key" : "display_name" ,
"required" : false
} ,
{
"key" : "role_code" ,
"required" : false
} ,
{
"key" : "delivery_basic_identity" ,
"required" : true
}
]
} ,
{
"domain" : "delivery" ,
"name" : "delivery_task" ,
"resource" : "/delivery/delivery_task" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "ec_order_identity" ,
"required" : true
} ,
{
"key" : "delivery_basic_identity" ,
"required" : true
} ,
{
"key" : "staff_account_identity" ,
"required" : false
}
]
} ,
{
"domain" : "delivery" ,
"name" : "delivery_track" ,
"resource" : "/delivery/delivery_track" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "delivery_task_identity" ,
"required" : true
} ,
{
"key" : "started_at" ,
"required" : false
} ,
{
"key" : "completed_at" ,
"required" : false
}
]
} ,
{
"domain" : "delivery" ,
"name" : "delivery_track_point" ,
"resource" : "/delivery/delivery_track_point" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "delivery_track_identity" ,
"required" : true
} ,
{
"key" : "point_type" ,
"required" : true
} ,
{
"key" : "occurred_at" ,
"required" : true
} ,
{
"key" : "longitude" ,
"required" : true
} ,
{
"key" : "latitude" ,
"required" : true
}
]
} ,
{
"domain" : "staff" ,
"name" : "staff_account" ,
"resource" : "/staff/account" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "username" ,
"required" : true
} ,
{
"key" : "password" ,
"required" : true
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "phone" ,
"required" : false
} ,
{
"key" : "avatar" ,
"required" : false
} ,
{
"key" : "role_code" ,
"required" : false
} ,
{
"key" : "gas_basic_identity" ,
"required" : false
} ,
{
"key" : "delivery_basic_identity" ,
"required" : false
} ,
{
"key" : "work_status" ,
"required" : false
}
]
} ,
{
"domain" : "staff" ,
"name" : "staff_credential" ,
"resource" : "/staff/credential" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "staff_account_identity" ,
"required" : true
} ,
{
"key" : "credential_type" ,
"required" : true
} ,
{
"key" : "credential_no" ,
"required" : false
} ,
{
"key" : "expired_at" ,
"required" : false
}
]
} ,
{
"domain" : "user" ,
"name" : "user_account" ,
"resource" : "/user/account" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "username" ,
"required" : true
} ,
{
"key" : "password" ,
"required" : true
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "phone" ,
"required" : false
} ,
{
"key" : "avatar" ,
"required" : false
} ,
{
"key" : "real_name" ,
"required" : false
}
]
} ,
{
"domain" : "user" ,
"name" : "user_address" ,
"resource" : "/user/address" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "user_account_identity" ,
"required" : true
} ,
{
"key" : "address" ,
"required" : true
} ,
{
"key" : "longitude" ,
"required" : false
} ,
{
"key" : "latitude" ,
"required" : false
} ,
{
"key" : "is_default" ,
"required" : false
}
]
} ,
{
"domain" : "user" ,
"name" : "user_service_relation" ,
"resource" : "/user/service_relation" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "user_account_identity" ,
"required" : true
} ,
{
"key" : "gas_basic_identity" ,
"required" : false
} ,
{
"key" : "delivery_basic_identity" ,
"required" : false
} ,
{
"key" : "staff_account_identity" ,
"required" : false
}
]
} ,
{
"domain" : "device" ,
"name" : "dev_smart_cylinder_valve" ,
"resource" : "/device/dev_smart_cylinder_valve" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "device_no" ,
"required" : true
} ,
{
"key" : "model" ,
"required" : false
} ,
{
"key" : "online_status" ,
"required" : false
} ,
{
"key" : "owner_identity" ,
"required" : false
}
]
} ,
{
"domain" : "device" ,
"name" : "dev_device_binding" ,
"resource" : "/device/dev_device_binding" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "smart_cylinder_valve_identity" ,
"required" : true
} ,
{
"key" : "user_account_identity" ,
"required" : true
} ,
{
"key" : "effective_at" ,
"required" : false
} ,
{
"key" : "expired_at" ,
"required" : false
}
]
} ,
{
"domain" : "device" ,
"name" : "dev_telemetry" ,
"resource" : "/device/dev_telemetry" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "smart_cylinder_valve_identity" ,
"required" : false
} ,
{
"key" : "recorded_at" ,
"required" : false
} ,
{
"key" : "payload" ,
"required" : false
}
]
} ,
{
"domain" : "safety" ,
"name" : "saf_rule" ,
"resource" : "/safety/saf_rule" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "rule_code" ,
"required" : true
} ,
{
"key" : "version_no" ,
"required" : false
} ,
{
"key" : "threshold" ,
"required" : false
} ,
{
"key" : "action" ,
"required" : false
} ,
{
"key" : "gray_scope" ,
"required" : false
}
]
} ,
{
"domain" : "safety" ,
"name" : "saf_event" ,
"resource" : "/safety/saf_event" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "event_code" ,
"required" : true
} ,
{
"key" : "level" ,
"required" : true
} ,
{
"key" : "title" ,
"required" : true
} ,
{
"key" : "smart_cylinder_valve_identity" ,
"required" : true
} ,
{
"key" : "sla_at" ,
"required" : false
}
]
} ,
{
"domain" : "safety" ,
"name" : "saf_inspection" ,
"resource" : "/safety/saf_inspection" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "user_account_identity" ,
"required" : true
} ,
{
"key" : "staff_account_identity" ,
"required" : true
} ,
{
"key" : "result" ,
"required" : true
} ,
{
"key" : "evidence_uri" ,
"required" : false
}
]
} ,
{
"domain" : "safety" ,
"name" : "saf_event_disposal" ,
"resource" : "/safety/saf_event/:identity/disposals" ,
"mode" : "append_only" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "action" ,
"required" : true
} ,
{
"key" : "reason" ,
"required" : true
}
]
} ,
{
"domain" : "ec" ,
"name" : "ec_category" ,
"resource" : "/ec/ec_category" ,
"mode" : "writable" ,
"pageKind" : "tree" ,
"fields" : [
{
"key" : "parent_identity" ,
"required" : false
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "sort_no" ,
"required" : false
}
]
} ,
{
"domain" : "ec" ,
"name" : "ec_product" ,
"resource" : "/ec/ec_product" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "ec_category_identity" ,
"required" : true
} ,
{
"key" : "product_code" ,
"required" : true
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "price_amount" ,
"required" : true
} ,
{
"key" : "stock_quantity" ,
"required" : false
}
]
} ,
{
"domain" : "ec" ,
"name" : "ec_product_attribute" ,
"resource" : "/ec/ec_product_attribute" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "ec_product_identity" ,
"required" : true
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "value" ,
"required" : true
} ,
{
"key" : "sort_no" ,
"required" : false
}
]
} ,
{
"domain" : "ec" ,
"name" : "ec_product_image" ,
"resource" : "/ec/ec_product_image" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "ec_product_identity" ,
"required" : true
} ,
{
"key" : "image_uri" ,
"required" : true
} ,
{
"key" : "sort_no" ,
"required" : false
} ,
{
"key" : "is_cover" ,
"required" : false
}
]
} ,
{
"domain" : "ec" ,
"name" : "ec_cart" ,
"resource" : "/ec/ec_cart" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "user_account_identity" ,
"required" : true
} ,
{
"key" : "ec_product_identity" ,
"required" : true
} ,
{
"key" : "quantity" ,
"required" : true
} ,
{
"key" : "selected" ,
"required" : false
}
]
} ,
{
"domain" : "ec" ,
"name" : "ec_order" ,
"resource" : "/ec/ec_order" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "user_account_identity" ,
"required" : true
} ,
{
"key" : "gas_basic_identity" ,
"required" : false
} ,
{
"key" : "delivery_basic_identity" ,
"required" : false
} ,
{
"key" : "order_no" ,
"required" : true
} ,
{
"key" : "total_amount" ,
"required" : true
}
]
} ,
{
"domain" : "ec" ,
"name" : "ec_order_item" ,
"resource" : "/ec/ec_order_item" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "ec_order_identity" ,
"required" : true
} ,
{
"key" : "ec_product_identity" ,
"required" : true
} ,
{
"key" : "product_snapshot" ,
"required" : true
} ,
{
"key" : "quantity" ,
"required" : true
} ,
{
"key" : "sale_amount" ,
"required" : true
}
]
} ,
{
"domain" : "ec" ,
"name" : "ec_review" ,
"resource" : "/ec/ec_review" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "ec_order_identity" ,
"required" : true
} ,
{
"key" : "ec_product_identity" ,
"required" : true
} ,
{
"key" : "user_account_identity" ,
"required" : true
} ,
{
"key" : "score" ,
"required" : true
} ,
{
"key" : "content" ,
"required" : true
}
]
} ,
{
"domain" : "finance" ,
"name" : "fin_payment" ,
"resource" : "/finance/fin_payment" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "ec_order_identity" ,
"required" : true
} ,
{
"key" : "channel" ,
"required" : true
} ,
{
"key" : "amount" ,
"required" : true
} ,
{
"key" : "paid_at" ,
"required" : false
}
]
} ,
{
"domain" : "finance" ,
"name" : "fin_settlement" ,
"resource" : "/finance/fin_settlement" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "settlement_no" ,
"required" : true
} ,
{
"key" : "subject_type" ,
"required" : true
} ,
{
"key" : "subject_identity" ,
"required" : true
} ,
{
"key" : "period_start" ,
"required" : true
} ,
{
"key" : "period_end" ,
"required" : true
}
]
} ,
{
"domain" : "finance" ,
"name" : "fin_reconciliation" ,
"resource" : "/finance/fin_reconciliation" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "channel" ,
"required" : true
} ,
{
"key" : "bill_date" ,
"required" : true
} ,
{
"key" : "difference_amount" ,
"required" : true
}
]
} ,
{
"domain" : "content" ,
"name" : "cnt_content" ,
"resource" : "/content/cnt_content" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "content_type" ,
"required" : true
} ,
{
"key" : "title" ,
"required" : true
} ,
{
"key" : "body" ,
"required" : true
} ,
{
"key" : "version_no" ,
"required" : false
} ,
{
"key" : "publish_status" ,
"required" : false
}
]
} ,
{
"domain" : "notification" ,
"name" : "ntf_template" ,
"resource" : "/notification/ntf_template" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "template_code" ,
"required" : true
} ,
{
"key" : "channel" ,
"required" : true
} ,
{
"key" : "content" ,
"required" : true
}
]
} ,
{
"domain" : "customer_service" ,
"name" : "cs_ticket" ,
"resource" : "/customer_service/cs_ticket" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "user_account_identity" ,
"required" : true
} ,
{
"key" : "ticket_no" ,
"required" : true
} ,
{
"key" : "category" ,
"required" : true
} ,
{
"key" : "priority" ,
"required" : true
}
]
} ,
{
"domain" : "platform" ,
"name" : "platfrom_account" ,
"resource" : "/platform/platfrom_account" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "username" ,
"required" : true
} ,
{
"key" : "password" ,
"required" : true
} ,
{
"key" : "display_name" ,
"required" : false
} ,
{
"key" : "avatar" ,
"required" : false
} ,
{
"key" : "platform_role_code" ,
"required" : false
} ,
{
"key" : "phone" ,
"required" : false
}
]
} ,
{
"domain" : "platform" ,
"name" : "platform_role" ,
"resource" : "/platform/platform_role" ,
"mode" : "writable" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "role_code" ,
"required" : true
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "data_scope" ,
"required" : true
}
]
} ,
{
"domain" : "platform" ,
"name" : "platform_menu" ,
"resource" : "/platform/platform_menu" ,
"mode" : "writable" ,
"pageKind" : "tree" ,
"fields" : [
{
"key" : "parent_identity" ,
"required" : false
} ,
{
"key" : "menu_code" ,
"required" : true
} ,
{
"key" : "name" ,
"required" : true
} ,
{
"key" : "icon" ,
"required" : false
} ,
{
"key" : "path" ,
"required" : false
} ,
{
"key" : "sort_no" ,
"required" : false
}
]
} ,
{
"domain" : "wallet" ,
"name" : "wallet" ,
"resource" : "/wallet/wallet" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "owner_identity" ,
"required" : false
} ,
{
"key" : "balance_amount" ,
"required" : false
} ,
{
"key" : "status" ,
"required" : false
}
]
} ,
{
"domain" : "wallet" ,
"name" : "wallet_ledger" ,
"resource" : "/wallet/wallet_ledger" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "wallet_identity" ,
"required" : false
} ,
{
"key" : "change_amount" ,
"required" : false
} ,
{
"key" : "balance_after" ,
"required" : false
}
]
} ,
{
"domain" : "wallet" ,
"name" : "wallet_recharge" ,
"resource" : "/wallet/wallet_recharge" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "wallet_identity" ,
"required" : false
} ,
{
"key" : "amount" ,
"required" : false
} ,
{
"key" : "status" ,
"required" : false
}
]
} ,
{
"domain" : "wallet" ,
"name" : "wallet_withdrawal" ,
"resource" : "/wallet/wallet_withdrawal" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "wallet_identity" ,
"required" : false
} ,
{
"key" : "amount" ,
"required" : false
} ,
{
"key" : "status" ,
"required" : false
}
]
} ,
{
"domain" : "report" ,
"name" : "report" ,
"resource" : "/report/report" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "report_code" ,
"required" : false
} ,
{
"key" : "name" ,
"required" : false
} ,
{
"key" : "status" ,
"required" : false
}
]
} ,
{
"domain" : "report" ,
"name" : "report_item" ,
"resource" : "/report/report_item" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "report_identity" ,
"required" : false
} ,
{
"key" : "metric_code" ,
"required" : false
} ,
{
"key" : "value" ,
"required" : false
}
]
} ,
{
"domain" : "report" ,
"name" : "report_metric_snapshot" ,
"resource" : "/report/report_metric_snapshot" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "report_identity" ,
"required" : false
} ,
{
"key" : "metric_code" ,
"required" : false
} ,
{
"key" : "value" ,
"required" : false
} ,
{
"key" : "captured_at" ,
"required" : false
}
]
} ,
{
"domain" : "audit" ,
"name" : "aud_operation_log" ,
"resource" : "/audit/aud_operation_log" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "operator_identity" ,
"required" : false
} ,
{
"key" : "action" ,
"required" : false
} ,
{
"key" : "object_identity" ,
"required" : false
} ,
{
"key" : "created_at" ,
"required" : false
}
]
} ,
{
"domain" : "audit" ,
"name" : "aud_export_log" ,
"resource" : "/audit/aud_export_log" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "operator_identity" ,
"required" : false
} ,
{
"key" : "resource_type" ,
"required" : false
} ,
{
"key" : "created_at" ,
"required" : false
}
]
} ,
{
"domain" : "audit" ,
"name" : "aud_approval" ,
"resource" : "/audit/aud_approval" ,
"mode" : "readonly" ,
"pageKind" : "list" ,
"fields" : [
{
"key" : "operator_identity" ,
"required" : false
} ,
{
"key" : "status" ,
"required" : false
} ,
{
"key" : "handled_at" ,
"required" : false
}
]
}
2026-07-27 01:11:38 +08:00
] ;
2026-07-27 09:56:33 +08:00
const source = fs . readFileSync ( 'src/api/resources.ts' , 'utf8' ) ;
2026-07-27 10:11:07 +08:00
const backendContractSource = fs . readFileSync ( '../../backend/api/internal/logic/platform/resource.go' , 'utf8' ) ;
const backendRouterSource = fs . readFileSync ( '../../backend/api/internal/routers/platform.go' , 'utf8' ) ;
2026-07-27 09:56:33 +08:00
const compiled = ts . transpileModule ( source , { compilerOptions : { module : ts . ModuleKind . CommonJS , target : ts . ScriptTarget . ES2020 } } ) . outputText ;
const resourceModule = { exports : { } } ;
vm . runInNewContext ( compiled , { module : resourceModule , exports : resourceModule . exports } ) ;
const resources = resourceModule . exports . resources ;
2026-07-27 09:44:08 +08:00
const files = ( dir ) => fs . existsSync ( dir ) ? fs . readdirSync ( dir , { withFileTypes : true } ) . flatMap ( ( entry ) => entry . isDirectory ( ) ? files ( path . join ( dir , entry . name ) ) : [ path . join ( dir , entry . name ) ] ) : [ ] ;
2026-07-27 09:56:33 +08:00
const sameFields = ( actual , expected ) => Array . isArray ( actual ) && actual . length === expected . length && actual . every ( ( field , index ) => field . key === expected [ index ] . key && Boolean ( field . required ) === Boolean ( expected [ index ] . required ) ) ;
2026-07-27 09:44:08 +08:00
function checkContracts ( ) {
const failures = [ ] ;
2026-07-27 09:56:33 +08:00
if ( ! Array . isArray ( resources ) || resources . length !== contracts . length ) failures . push ( ` catalogue: expected ${ contracts . length } resources ` ) ;
for ( const contract of contracts ) {
const definition = resources . find ( ( resource ) => resource . name === contract . name ) ;
const label = ` ${ contract . domain } / ${ contract . name } ` ;
if ( ! definition || definition . resource !== contract . resource || definition . mode !== contract . mode || definition . pageKind !== contract . pageKind || ! sameFields ( definition . fields , contract . fields ) ) failures . push ( ` ${ label } : mismatched contract or allowlist ` ) ;
2026-07-27 10:11:07 +08:00
if ( ! backendContractSource . includes ( ` Domain: " ${ contract . domain } " ` ) || ! backendContractSource . includes ( ` Name: " ${ contract . name } " ` ) ) failures . push ( ` ${ label } : absent from backend ExpectedResources ` ) ;
if ( contract . name !== 'saf_event_disposal' && ! backendRouterSource . includes ( contract . resource ) ) failures . push ( ` ${ label } : absent from backend router ` ) ;
2026-07-27 09:56:33 +08:00
const requiredIdentity = contract . fields . filter ( ( field ) => field . required && field . key . endsWith ( '_identity' ) ) . map ( ( field ) => field . key ) ;
if ( definition && JSON . stringify ( definition . requiredIdentities ? ? [ ] ) !== JSON . stringify ( requiredIdentity ) ) failures . push ( ` ${ label } : required identity fields do not match allowlist ` ) ;
if ( contract . name === 'saf_event_disposal' ) continue ;
const route = path . join ( 'src/router/routes/modules' , contract . domain + '.ts' ) ;
if ( ! fs . existsSync ( route ) || ! fs . readFileSync ( route , 'utf8' ) . includes ( contract . name ) ) failures . push ( ` ${ label } : missing route ` ) ;
const page = path . join ( 'src/views' , contract . domain , contract . name , contract . pageKind === 'tree' ? 'TreePage.vue' : 'ListPage.vue' ) ;
2026-07-27 09:44:08 +08:00
if ( ! fs . existsSync ( page ) ) failures . push ( ` ${ label } : missing view ` ) ;
2026-07-27 09:56:33 +08:00
if ( contract . mode === 'readonly' && ( ! fs . existsSync ( page ) || ! fs . readFileSync ( page , 'utf8' ) . includes ( 'ReadOnlyListPage' ) ) ) failures . push ( ` ${ label } : readonly page exposes write surface ` ) ;
2026-07-27 00:18:42 +08:00
}
2026-07-27 09:56:33 +08:00
const names = resources . map ( ( resource ) => resource . name ) . sort ( ) ;
const expectedNames = contracts . map ( ( contract ) => contract . name ) . sort ( ) ;
if ( JSON . stringify ( names ) !== JSON . stringify ( expectedNames ) ) failures . push ( 'catalogue: resource names do not equal ExpectedResources' ) ;
if ( resources . some ( ( resource ) => resource . fields . some ( ( field ) => field . key === 'id' || field . key . endsWith ( '_id' ) ) ) ) failures . push ( 'catalogue: internal identifier leaked through fields' ) ;
2026-07-27 09:44:08 +08:00
const readonlyPage = fs . readFileSync ( 'src/views/shared/ReadOnlyListPage.vue' , 'utf8' ) ;
2026-07-27 09:56:33 +08:00
if ( /(CrudListPage|resourceApi\\.(create|update|archive|updateStatus))/ . test ( readonlyPage ) ) failures . push ( 'readonly shared page: contains write surface' ) ;
2026-07-27 09:44:08 +08:00
const treePage = fs . readFileSync ( 'src/views/shared/TreePage.vue' , 'utf8' ) ;
2026-07-27 10:11:07 +08:00
if ( ! treePage . includes ( '<a-tree' ) || ! treePage . includes ( 'parent_identity' ) || /\bparent_id\b|\bid\b/ . test ( treePage ) || treePage . includes ( 'CrudListPage' ) ) failures . push ( 'tree shared page: must be identity-first' ) ;
2026-07-27 09:56:33 +08:00
for ( const name of [ 'ec_category' , 'platform_menu' ] ) { const view = path . join ( 'src/views' , name === 'ec_category' ? 'ec' : 'platform' , name , 'TreePage.vue' ) ; if ( ! fs . existsSync ( view ) ) failures . push ( ` ${ name } : must use TreePage ` ) ; }
const safetyEvent = resources . find ( ( resource ) => resource . name === 'saf_event' ) ;
if ( ! safetyEvent ? . detailActions ? . some ( ( item ) => item . name === 'saf_event_disposal' && item . resource === '/safety/saf_event/:identity/disposals' ) ) failures . push ( 'safety event: missing disposal detail action' ) ;
if ( files ( 'src/router/routes/modules' ) . some ( ( file ) => fs . readFileSync ( file , 'utf8' ) . includes ( 'saf_event_disposal' ) ) || fs . existsSync ( 'src/views/safety/saf_event_disposal' ) ) failures . push ( 'saf_event_disposal: must not have independent menu or page' ) ;
2026-07-27 09:44:08 +08:00
const crudSource = fs . readFileSync ( 'src/views/shared/CrudListPage.vue' , 'utf8' ) ;
if ( ! crudSource . includes ( "key !== 'id'" ) || ! crudSource . includes ( "key.endsWith('_id')" ) ) failures . push ( 'detail view: does not remove internal identifiers' ) ;
2026-07-27 09:56:33 +08:00
const leakedUiFiles = files ( 'src/api' ) . concat ( files ( 'src/views' ) ) . filter ( ( file ) => / \ . ( ts | vue ) $ / . test ( file ) && ! file . endsWith ( 'CrudListPage.vue' ) && ! file . endsWith ( 'ReadOnlyListPage.vue' ) && ! file . endsWith ( 'TreePage.vue' ) ) . filter ( ( file ) => / \ b [ A - Za - z ] [ A - Za - z0 - 9 ] * _id \ b | \ bid \ b / . test ( fs . readFileSync ( file , 'utf8' ) ) ) ;
if ( leakedUiFiles . length ) failures . push ( ` identity leak: ${ leakedUiFiles . join ( ', ' ) } ` ) ;
if ( /data-index="(?:id|[^" ]+_id)"|\{\{\s*[^}]*\b(?:id|[A-Za-z][A-Za-z0-9]*_id)\b/ . test ( treePage ) ) failures . push ( 'tree page: displays internal identifier' ) ;
2026-07-27 09:44:08 +08:00
return failures ;
2026-07-27 00:18:42 +08:00
}
2026-07-27 09:44:08 +08:00
const failures = checkContracts ( ) ;
for ( const failure of failures ) console . log ( failure ) ;
if ( failures . length ) process . exitCode = 1 ;