{"numFailedTestSuites":0,"numFailedTests":0,"numPassedTestSuites":9,"numPassedTests":127,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":9,"numTotalTests":127,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1791304161103,"success":true,"testResults":[{"assertionResults":[{"ancestorTitles":["HTTP channel flow"],"duration":36,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow runs health checks and Swagger","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"runs health checks and Swagger"},{"ancestorTitles":["HTTP channel flow"],"duration":23,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow logs in using wx.login code without leaking WeChat identifiers or session_key","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"logs in using wx.login code without leaking WeChat identifiers or session_key"},{"ancestorTitles":["HTTP channel flow"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow rejects forged login identity fields","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects forged login identity fields"},{"ancestorTitles":["HTTP channel flow"],"duration":6,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow distinguishes missing session from missing contact binding","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"distinguishes missing session from missing contact binding"},{"ancestorTitles":["HTTP channel flow"],"duration":19,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow binds a WeChat-verified phone then resolves contact server-side","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"binds a WeChat-verified phone then resolves contact server-side"},{"ancestorTitles":["HTTP channel flow"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow returns 503 without connection details when the channel database is unavailable","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"returns 503 without connection details when the channel database is unavailable"},{"ancestorTitles":["HTTP channel flow"],"duration":14,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow clears contact on phone change and rejects stale contact resolver responses","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"clears contact on phone change and rejects stale contact resolver responses"},{"ancestorTitles":["HTTP channel flow"],"duration":30,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow submits a verified email and business card and queues the review notification","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"submits a verified email and business card and queues the review notification"},{"ancestorTitles":["HTTP channel flow"],"duration":4,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow rejects a spoofed business-card MIME type","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"status":"passed","title":"rejects a spoofed business-card MIME type"},{"ancestorTitles":["HTTP channel flow"],"duration":13,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow invalidates binding if NDB no longer resolves the contact","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"invalidates binding if NDB no longer resolves the contact"},{"ancestorTitles":["HTTP channel flow"],"duration":4,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow projects public meetings without private links or Task data","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"projects public meetings without private links or Task data"},{"ancestorTitles":["HTTP channel flow"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow returns the NDB-derived meeting banners without authentication","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"returns the NDB-derived meeting banners without authentication"},{"ancestorTitles":["HTTP channel flow"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow forwards validated date and month calendar filters to NDB","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"forwards validated date and month calendar filters to NDB"},{"ancestorTitles":["HTTP channel flow"],"duration":9,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow serves the V2 content, topic and public expert catalog without private fields","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"serves the V2 content, topic and public expert catalog without private fields"},{"ancestorTitles":["HTTP channel flow"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow derives a unique industry list from the public V2 catalog","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"derives a unique industry list from the public V2 catalog"},{"ancestorTitles":["HTTP channel flow"],"duration":11,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow creates an expert interview request from the authenticated bound contact","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"creates an expert interview request from the authenticated bound contact"},{"ancestorTitles":["HTTP channel flow"],"duration":12,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow rejects an invalid interview idempotency key before calling NDB","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects an invalid interview idempotency key before calling NDB"},{"ancestorTitles":["HTTP channel flow"],"duration":11,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow returns my meetings from NDB using bound contact","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"returns my meetings from NDB using bound contact"},{"ancestorTitles":["HTTP channel flow"],"duration":11,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow forwards user idempotency key and derives contact from session","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"forwards user idempotency key and derives contact from session"},{"ancestorTitles":["HTTP channel flow"],"duration":12,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow cancels via NDB and keeps local finance absent","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"cancels via NDB and keeps local finance absent"},{"ancestorTitles":["HTTP channel flow"],"duration":21,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow keeps favorites and reminder preferences separate from registration/Task calls","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"keeps favorites and reminder preferences separate from registration/Task calls"},{"ancestorTitles":["HTTP channel flow"],"duration":26,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow uses unified NDB minutes GET, PUT and mine DTOs without financial state or attend mutations","invocations":1,"location":null,"numPassingAsserts":14,"retryReasons":[],"status":"passed","title":"uses unified NDB minutes GET, PUT and mine DTOs without financial state or attend mutations"},{"ancestorTitles":["HTTP channel flow"],"duration":35,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow projects one registration and Task across minutes-only, both intents, and attendance cancellation","invocations":1,"location":null,"numPassingAsserts":15,"retryReasons":[],"status":"passed","title":"projects one registration and Task across minutes-only, both intents, and attendance cancellation"},{"ancestorTitles":["HTTP channel flow"],"duration":13,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow returns null from NDB despite a legacy minutes preference","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"returns null from NDB despite a legacy minutes preference"},{"ancestorTitles":["HTTP channel flow"],"duration":24,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow requires authenticated bound identity, validates keys, and refuses cancellation on /api/v2/meetings/1/minutes-subscription","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"requires authenticated bound identity, validates keys, and refuses cancellation on /api/v2/meetings/1/minutes-subscription"},{"ancestorTitles":["HTTP channel flow"],"duration":31,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow requires authenticated bound identity, validates keys, and refuses cancellation on /api/v2/notifications/subscriptions/1/minutes","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"requires authenticated bound identity, validates keys, and refuses cancellation on /api/v2/notifications/subscriptions/1/minutes"},{"ancestorTitles":["HTTP channel flow"],"duration":18,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow rejects a wrong-intent or wrong-owner mine result on /api/v2/meetings/my","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects a wrong-intent or wrong-owner mine result on /api/v2/meetings/my"},{"ancestorTitles":["HTTP channel flow"],"duration":19,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow rejects a wrong-intent or wrong-owner mine result on /api/v2/meetings/minutes-reservations/mine","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects a wrong-intent or wrong-owner mine result on /api/v2/meetings/minutes-reservations/mine"},{"ancestorTitles":["HTTP channel flow"],"duration":12,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow rejects a wrong-intent or wrong-owner mine result on /api/v2/meetings/my","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects a wrong-intent or wrong-owner mine result on /api/v2/meetings/my"},{"ancestorTitles":["HTTP channel flow"],"duration":16,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow passes explicit minutes keys and rejects stale identity and cross-contact upstream responses","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"passes explicit minutes keys and rejects stale identity and cross-contact upstream responses"},{"ancestorTitles":["HTTP channel flow"],"duration":19,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow persists one no-contract refusal notice across both minutes paths without masking the rejection","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"status":"passed","title":"persists one no-contract refusal notice across both minutes paths without masking the rejection"},{"ancestorTitles":["HTTP channel flow"],"duration":14,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow does not impose BFF time or pricing gates and preserves the NDB human-minutes refusal","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"does not impose BFF time or pricing gates and preserves the NDB human-minutes refusal"},{"ancestorTitles":["HTTP channel flow"],"duration":9,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow preserves NO_ACTIVE_CONTRACT even if the refusal cannot be persisted","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"preserves NO_ACTIVE_CONTRACT even if the refusal cannot be persisted"},{"ancestorTitles":["HTTP channel flow"],"duration":13,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow enforces ownership on favorites and message read operations","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"enforces ownership on favorites and message read operations"},{"ancestorTitles":["HTTP channel flow"],"duration":10,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow retrieves join link with meeting:join scope only for a bound session","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"retrieves join link with meeting:join scope only for a bound session"},{"ancestorTitles":["HTTP channel flow"],"duration":9,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow hides join link on REGISTRATION_REQUIRED","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"hides join link on REGISTRATION_REQUIRED"},{"ancestorTitles":["HTTP channel flow"],"duration":10,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow hides join link on MEETING_NOT_OPEN","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"hides join link on MEETING_NOT_OPEN"},{"ancestorTitles":["HTTP channel flow"],"duration":8,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow hides join link on JOIN_LINK_UNAVAILABLE","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"hides join link on JOIN_LINK_UNAVAILABLE"},{"ancestorTitles":["HTTP channel flow"],"duration":10,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow guides contract errors and upstream downtime without exposing provider messages","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"guides contract errors and upstream downtime without exposing provider messages"},{"ancestorTitles":["HTTP channel flow"],"duration":10,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow revokes all prior tokens on logout","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"status":"passed","title":"revokes all prior tokens on logout"},{"ancestorTitles":["HTTP channel flow"],"duration":4,"failureDetails":[],"failureMessages":[],"fullName":"HTTP channel flow rejects expired JWT and legacy conference routes","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"status":"passed","title":"rejects expired JWT and legacy conference routes"}],"endTime":1791304163758,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/http.spec.ts","startTime":1791304161255,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["SQLite source preservation and database guard"],"duration":192,"failureDetails":[],"failureMessages":[],"fullName":"SQLite source preservation and database guard reads version 1 without upgrading it, preserving identities and defaulting new fields","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"status":"passed","title":"reads version 1 without upgrading it, preserving identities and defaulting new fields"},{"ancestorTitles":["SQLite source preservation and database guard"],"duration":333,"failureDetails":[],"failureMessages":[],"fullName":"SQLite source preservation and database guard preserves version 3 binary cards, verification state and retry counters","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"status":"passed","title":"preserves version 3 binary cards, verification state and retry counters"},{"ancestorTitles":["SQLite source preservation and database guard"],"duration":16,"failureDetails":[],"failureMessages":[],"fullName":"SQLite source preservation and database guard refuses an unsupported source version and never creates a missing file","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"refuses an unsupported source version and never creates a missing file"},{"ancestorTitles":["SQLite source preservation and database guard"],"duration":6,"failureDetails":[],"failureMessages":[],"fullName":"SQLite source preservation and database guard rejects missing required source columns rather than inventing identity fields","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects missing required source columns rather than inventing identity fields"},{"ancestorTitles":["SQLite source preservation and database guard"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"SQLite source preservation and database guard refuses a non-channel connection target","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"refuses a non-channel connection target"},{"ancestorTitles":["SQLite source preservation and database guard"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"SQLite source preservation and database guard refuses a non-channel connection target","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"refuses a non-channel connection target"},{"ancestorTitles":["SQLite source preservation and database guard"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"SQLite source preservation and database guard refuses a non-channel connection target","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"refuses a non-channel connection target"}],"endTime":1791304164348,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/sqlite-import.spec.ts","startTime":1791304163762,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["minutes refusal durable outbox"],"duration":26,"failureDetails":[],"failureMessages":[],"fullName":"minutes refusal durable outbox marks missing configuration and resumes after restart without changing the refusal identity","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"marks missing configuration and resumes after restart without changing the refusal identity"},{"ancestorTitles":["minutes refusal durable outbox"],"duration":6,"failureDetails":[],"failureMessages":[],"fullName":"minutes refusal durable outbox persists missing service configuration across a retry tick, with no delivery claim","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"persists missing service configuration across a retry tick, with no delivery claim"},{"ancestorTitles":["minutes refusal durable outbox"],"duration":9,"failureDetails":[],"failureMessages":[],"fullName":"minutes refusal durable outbox retries failures with the same dedup key after restart, applies backoff and honors the minutes recipient","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"status":"passed","title":"retries failures with the same dedup key after restart, applies backoff and honors the minutes recipient"},{"ancestorTitles":["minutes refusal durable outbox"],"duration":8,"failureDetails":[],"failureMessages":[],"fullName":"minutes refusal durable outbox deduplicates by meeting/contact across users without merging distinct meetings","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"deduplicates by meeting/contact across users without merging distinct meetings"},{"ancestorTitles":["minutes refusal durable outbox"],"duration":8,"failureDetails":[],"failureMessages":[],"fullName":"minutes refusal durable outbox additively upgrades version 4 without migrating legacy minutes into Tasks or notices","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"additively upgrades version 4 without migrating legacy minutes into Tasks or notices"}],"endTime":1791304164503,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/minutes-outbox.spec.ts","startTime":1791304164350,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["identity state and contact events"],"duration":30,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events auto binds an initial or newly added number only after current NDB resolution","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"auto binds an initial or newly added number only after current NDB resolution"},{"ancestorTitles":["identity state and contact events"],"duration":25,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events requires a full application after a WeChat phone change before accepting replacement number","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"status":"passed","title":"requires a full application after a WeChat phone change before accepting replacement number"},{"ancestorTitles":["identity state and contact events"],"duration":17,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events blocks proactive auto binding during delayed MQ delivery of a replacement event","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"blocks proactive auto binding during delayed MQ delivery of a replacement event"},{"ancestorTitles":["identity state and contact events"],"duration":18,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events rejects a later replacement even when the same number was previously fully authenticated","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"rejects a later replacement even when the same number was previously fully authenticated"},{"ancestorTitles":["identity state and contact events"],"duration":22,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events does not let an old contact event revoke a newer completed authentication","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"does not let an old contact event revoke a newer completed authentication"},{"ancestorTitles":["identity state and contact events"],"duration":20,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events keeps an unmatched application pending, then authorizes it when NDB adds the number","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"keeps an unmatched application pending, then authorizes it when NDB adds the number"},{"ancestorTitles":["identity state and contact events"],"duration":24,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events handles added and replaced contact events idempotently without undoing later full authentication","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"handles added and replaced contact events idempotently without undoing later full authentication"},{"ancestorTitles":["identity state and contact events"],"duration":16,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events rejects an application if the verified phone changes away and back during NDB resolution","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"rejects an application if the verified phone changes away and back during NDB resolution"},{"ancestorTitles":["identity state and contact events"],"duration":21,"failureDetails":[],"failureMessages":[],"fullName":"identity state and contact events retries review notification submission with the same idempotency key","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"status":"passed","title":"retries review notification submission with the same idempotency key"}],"endTime":1791304164803,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/identity.spec.ts","startTime":1791304164505,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["WeChat boundary"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"WeChat boundary discards session_key and rejects absent openid","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"discards session_key and rejects absent openid"},{"ancestorTitles":["WeChat boundary"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"WeChat boundary maps expired codes and upstream network failure","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"maps expired codes and upstream network failure"},{"ancestorTitles":["WeChat boundary"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"WeChat boundary verifies phone watermark appid before binding","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"verifies phone watermark appid before binding"},{"ancestorTitles":["WeChat boundary"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"WeChat boundary coalesces token acquisition for concurrent phone requests","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"coalesces token acquisition for concurrent phone requests"},{"ancestorTitles":["channel-only versioned PostgreSQL SQL contract"],"duration":24,"failureDetails":[],"failureMessages":[],"fullName":"channel-only versioned PostgreSQL SQL contract preserves channel identities and favorite state over migration rerun","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"preserves channel identities and favorite state over migration rerun"}],"endTime":1791304164960,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/wechat-storage.spec.ts","startTime":1791304164806,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["NDB signature contract"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB signature contract uses RFC3986, repeated keys, blanks and lexicographic key/value ordering","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"uses RFC3986, repeated keys, blanks and lexicographic key/value ordering"},{"ancestorTitles":["NDB signature contract"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB signature contract signs the exact six-line request and exact UTF-8 body","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"signs the exact six-line request and exact UTF-8 body"},{"ancestorTitles":["NDB signature contract"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB signature contract matches a vector generated by the existing NDB Python implementation","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"matches a vector generated by the existing NDB Python implementation"},{"ancestorTitles":["NDB signature contract"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB signature contract hashes an empty GET body","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"hashes an empty GET body"},{"ancestorTitles":["NDB signature contract"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB signature contract uses collision-safe tuple boundaries for business keys","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"uses collision-safe tuple boundaries for business keys"},{"ancestorTitles":["configuration and boundary validation"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation accepts configured development","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"accepts configured development"},{"ancestorTitles":["configuration and boundary validation"],"duration":4,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation does not expose submitted secrets in validation errors","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"does not expose submitted secrets in validation errors"},{"ancestorTitles":["configuration and boundary validation"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation requires safe production configuration {\"NDB_BASE_URL\": \"http://ndb.test\"}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"requires safe production configuration {\"NDB_BASE_URL\": \"http://ndb.test\"}"},{"ancestorTitles":["configuration and boundary validation"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation requires safe production configuration {\"CHANNEL_DATABASE_URL\": \"sqlite://memory\", \"NDB_BASE_URL\": \"https://ndb.test\"}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"requires safe production configuration {\"CHANNEL_DATABASE_URL\": \"sqlite://memory\", \"NDB_BASE_URL\": \"https://ndb.test\"}"},{"ancestorTitles":["configuration and boundary validation"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation rejects non-origin NDB URL ftp://ndb.test","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects non-origin NDB URL ftp://ndb.test"},{"ancestorTitles":["configuration and boundary validation"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation rejects non-origin NDB URL https://user:password@ndb.test","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects non-origin NDB URL https://user:password@ndb.test"},{"ancestorTitles":["configuration and boundary validation"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation rejects non-origin NDB URL https://ndb.test/api","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects non-origin NDB URL https://ndb.test/api"},{"ancestorTitles":["configuration and boundary validation"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation rejects non-origin NDB URL https://ndb.test/?secret=bad","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects non-origin NDB URL https://ndb.test/?secret=bad"},{"ancestorTitles":["configuration and boundary validation"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"configuration and boundary validation rejects ID coercion and invalid idempotency headers","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"rejects ID coercion and invalid idempotency headers"}],"endTime":1791304165095,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/signature.spec.ts","startTime":1791304164963,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["NDB transport and typed adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter accepts the real NDB envelope and strips Task state","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"accepts the real NDB envelope and strips Task state"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter sends a fresh nonce and stable business key for retries","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"sends a fresh nonce and stable business key for retries"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter returns original registration on duplicate conflict","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"returns original registration on duplicate conflict"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter fails closed on a cross-contact registration","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"fails closed on a cross-contact registration"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter returns null for no registration","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"returns null for no registration"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps MEETING_NOT_OPEN without leaking upstream text","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps MEETING_NOT_OPEN without leaking upstream text"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps NO_ACTIVE_CONTRACT without leaking upstream text","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps NO_ACTIVE_CONTRACT without leaking upstream text"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps AMBIGUOUS_PROJECT without leaking upstream text","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps AMBIGUOUS_PROJECT without leaking upstream text"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps AMBIGUOUS_CONTRACT without leaking upstream text","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps AMBIGUOUS_CONTRACT without leaking upstream text"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps IDEMPOTENCY_CONFLICT without leaking upstream text","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps IDEMPOTENCY_CONFLICT without leaking upstream text"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps upstream authentication 401 as server configuration, not user login","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps upstream authentication 401 as server configuration, not user login"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps upstream authentication 403 as server configuration, not user login","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps upstream authentication 403 as server configuration, not user login"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps upstream availability 429","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps upstream availability 429"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps upstream availability 500","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps upstream availability 500"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps upstream availability 503","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps upstream availability 503"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps network timeout and does not blindly retry writes","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"maps network timeout and does not blindly retry writes"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter rejects an incompatible contract {\"data\": [Array], \"err\": 0}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects an incompatible contract {\"data\": [Array], \"err\": 0}"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter rejects an incompatible contract {\"code\": 200, \"data\": [Object]}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects an incompatible contract {\"code\": 200, \"data\": [Object]}"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter requires the confirmed public detail fields and excludes private expert data","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"status":"passed","title":"requires the confirmed public detail fields and excludes private expert data"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter reads the server-derived banner list with the conference read scope","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"reads the server-derived banner list with the conference read scope"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter maps an application-owned meeting miss to NOT_FOUND","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"maps an application-owned meeting miss to NOT_FOUND"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter refuses paths and scopes outside application credentials","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"refuses paths and scopes outside application credentials"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter validates catalog contracts and derives a stable interview idempotency key","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"validates catalog contracts and derives a stable interview idempotency key"},{"ancestorTitles":["NDB transport and typed adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB transport and typed adapter deduplicates industries exposed by all public catalog collections","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"deduplicates industries exposed by all public catalog collections"}],"endTime":1791304165210,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/ndb-client.spec.ts","startTime":1791304165097,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["NDB minutes business adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter uses a separate stable business key, fresh nonces and only the verified contact payload","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"status":"passed","title":"uses a separate stable business key, fresh nonces and only the verified contact payload"},{"ancestorTitles":["NDB minutes business adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter preserves the NDB timestamp 2026-10-07T00:26:08.883534 for both business intents","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"preserves the NDB timestamp 2026-10-07T00:26:08.883534 for both business intents"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter preserves the NDB timestamp 2026-10-07T00:26:08 for both business intents","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"preserves the NDB timestamp 2026-10-07T00:26:08 for both business intents"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter preserves the NDB timestamp 2026-10-07T00:26:08.883534Z for both business intents","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"preserves the NDB timestamp 2026-10-07T00:26:08.883534Z for both business intents"},{"ancestorTitles":["NDB minutes business adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter preserves the NDB timestamp 2026-10-07T00:26:08.883534+08:00 for both business intents","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"preserves the NDB timestamp 2026-10-07T00:26:08.883534+08:00 for both business intents"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter continues rejecting invalid registration timestamps 2026-02-30T00:26:08.883534","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"continues rejecting invalid registration timestamps 2026-02-30T00:26:08.883534"},{"ancestorTitles":["NDB minutes business adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter continues rejecting invalid registration timestamps 2026-10-07T24:26:08","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"continues rejecting invalid registration timestamps 2026-10-07T24:26:08"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter continues rejecting invalid registration timestamps 2026-10-07T00:60:08","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"continues rejecting invalid registration timestamps 2026-10-07T00:60:08"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter continues rejecting invalid registration timestamps 2026-10-07","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"continues rejecting invalid registration timestamps 2026-10-07"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter continues rejecting invalid registration timestamps garbage","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"continues rejecting invalid registration timestamps garbage"},{"ancestorTitles":["NDB minutes business adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter rejects malformed or cross-owner business facts {\"meeting_id\": 2}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects malformed or cross-owner business facts {\"meeting_id\": 2}"},{"ancestorTitles":["NDB minutes business adapter"],"duration":4,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter rejects malformed or cross-owner business facts {\"client_contact_id\": 21}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects malformed or cross-owner business facts {\"client_contact_id\": 21}"},{"ancestorTitles":["NDB minutes business adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter rejects malformed or cross-owner business facts {\"task_id\": null}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects malformed or cross-owner business facts {\"task_id\": null}"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter rejects malformed or cross-owner business facts {\"minutes_requested\": false}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects malformed or cross-owner business facts {\"minutes_requested\": false}"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter rejects malformed or cross-owner business facts {\"created_at\": \"invalid\"}","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"rejects malformed or cross-owner business facts {\"created_at\": \"invalid\"}"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter returns authoritative null and read scope for state without writes","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"returns authoritative null and read scope for state without writes"},{"ancestorTitles":["NDB minutes business adapter"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter projects attend-only as no minutes and retains minutes when attendance is cancelled","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"projects attend-only as no minutes and retains minutes when attendance is cancelled"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter maps published human-minutes and no-contract refusals without rewriting them","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"maps published human-minutes and no-contract refusals without rewriting them"},{"ancestorTitles":["NDB minutes business adapter"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"NDB minutes business adapter does not automatically retry a timed-out business mutation","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"does not automatically retry a timed-out business mutation"}],"endTime":1791304165301,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/minutes-adapter.spec.ts","startTime":1791304165215,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["renderMiniProgramRichText"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"renderMiniProgramRichText converts Markdown into HTML supported by the mini program rich-text component","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"converts Markdown into HTML supported by the mini program rich-text component"},{"ancestorTitles":["renderMiniProgramRichText"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"renderMiniProgramRichText keeps legacy HTML while removing unsafe markup and attributes","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"keeps legacy HTML while removing unsafe markup and attributes"},{"ancestorTitles":["renderMiniProgramRichText"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"renderMiniProgramRichText rejects unsafe links","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"rejects unsafe links"}],"endTime":1791304165357,"message":"","name":"/Users/gexiaowei/Documents/work/mindsetech/ndb/projects/mp/mp-conference-api-v2/test/rich-text.spec.ts","startTime":1791304165306,"status":"passed","summary":""}],"wasInterrupted":false}
