Skip to content

Conversation

@jackjain
Copy link
Contributor

@jackjain jackjain commented Jan 16, 2026

  • Added possible flow/sequence diagram for different scenarios
  • Added API contract
  • Added Cache design
  • Added design for vc-verifier library change

Summary by CodeRabbit

  • Documentation
    • Added comprehensive design documentation for Verifiable Credentials status checks covering viewing and user-initiated checks, add/ingest flows, API response formats, status caching strategy (24h TTL), database fields and migration guidance, and verifier integration points to surface status results.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 16, 2026

Walkthrough

A new design document details a Verifiable Credentials (VC) status-check system: workflows for viewing, user-initiated, and add-time checks; API contracts; database schema changes; a 24-hour status-list cache; and integration points/adjustments for the VC Verifier library.

Changes

Cohort / File(s) Summary
VC Status Check Design Documentation
docs/VCStatusCheckDesign.md
New design doc describing: three status-check flows (view, user-check, add-time); API response shapes (isSchemaAndSignatureValid, isExpired, statusChecks, lastCheckedAt, detailed single-check responses); DB schema additions (is_expired, is_schema_signature_valid, status_checks, status_last_checked_at) and migration notes; status-list credential cache (24h TTL, structure); VC Verifier API change to accept optional statusListCredentialCache and return status-list credentials in results.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API
    participant DB
    participant Cache
    participant Verifier
    participant ExternalStatusList

    Client->>API: Request credential(s) with status
    API->>DB: Fetch stored VC records
    DB-->>API: Return VC(s)
    API->>Cache: Check status-list credential cache (per VC)
    alt Cache hit
        Cache-->>API: Return status-list credential
    else Cache miss
        API->>Verifier: Request status list credential (verify & fetch)
        Verifier->>ExternalStatusList: Fetch status list credential
        ExternalStatusList-->>Verifier: Return status list credential
        Verifier-->>API: Return status-list credential result
        API->>Cache: Store status-list credential (24h TTL)
    end
    API->>Verifier: Verify VC schema/signature and check status using status-list credential
    Verifier-->>API: Return status and schema/signature verdicts
    API->>DB: Update `status_checks` and `status_last_checked_at` (if configured)
    API-->>Client: Respond with VC(s) and status fields (isSchemaAndSignatureValid, isExpired, statusChecks, lastCheckedAt)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I hop through schemas, flags held high, 🐰
Caching lists beneath the sky,
I check a VC with careful glance,
Update the records, skip and dance,
A rabbit's nod to verification nigh.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: adding technical documentation for VC status check design, directly matching the changeset content.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


🧹 Recent nitpick comments
docs/VCStatusCheckDesign.md (2)

9-9: Fix heading formatting.

The heading should be hyphenated for proper grammar: "High-level user flow" instead of "High level user flow".

📝 Proposed fix
-### High level user flow
+### High-level user flow

135-135: Fix typo in sequence diagram participant.

"PostgresSQL" should be "PostgreSQL".

📝 Proposed fix
-    participant Database as Database(PostgresSQL)
+    participant Database as Database(PostgreSQL)

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d96b961 and e586ba6.

📒 Files selected for processing (1)
  • docs/VCStatusCheckDesign.md
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: jackjain
Repo: inji/mimoto PR: 995
File: docs/VCStatusCheckDesign.md:66-66
Timestamp: 2026-01-16T02:19:06.698Z
Learning: In the VC Status Check design for Inji Web/Mimoto, the `lastCheckedAt` field intentionally has different semantics across flows: when using cached status list data (Flow 1), `lastCheckedAt` is set to the cache creation time; when performing realtime status checks with issuer data (Flow 2), `lastCheckedAt` is set to the current time. This difference reflects whether the check relies on cached or fresh data.
Learnt from: jackjain
Repo: inji/mimoto PR: 995
File: docs/VCStatusCheckDesign.md:300-300
Timestamp: 2026-01-16T02:30:15.809Z
Learning: In the VC Status Check design for Inji Web/Mimoto, the `status_last_checked_at` field in the `verifiable_credential` table is NOT NULL with no default value. This is valid because status checks are performed synchronously during credential addition, and if the status check fails, the entire credential addition operation fails. The credential is only stored in the database after a successful status check, ensuring `status_last_checked_at` always has a value.
📚 Learning: 2026-01-16T02:30:15.809Z
Learnt from: jackjain
Repo: inji/mimoto PR: 995
File: docs/VCStatusCheckDesign.md:300-300
Timestamp: 2026-01-16T02:30:15.809Z
Learning: In the VC Status Check design for Inji Web/Mimoto, the `status_last_checked_at` field in the `verifiable_credential` table is NOT NULL with no default value. This is valid because status checks are performed synchronously during credential addition, and if the status check fails, the entire credential addition operation fails. The credential is only stored in the database after a successful status check, ensuring `status_last_checked_at` always has a value.

Applied to files:

  • docs/VCStatusCheckDesign.md
📚 Learning: 2026-01-16T02:19:06.698Z
Learnt from: jackjain
Repo: inji/mimoto PR: 995
File: docs/VCStatusCheckDesign.md:66-66
Timestamp: 2026-01-16T02:19:06.698Z
Learning: In the VC Status Check design for Inji Web/Mimoto, the `lastCheckedAt` field intentionally has different semantics across flows: when using cached status list data (Flow 1), `lastCheckedAt` is set to the cache creation time; when performing realtime status checks with issuer data (Flow 2), `lastCheckedAt` is set to the current time. This difference reflects whether the check relies on cached or fresh data.

Applied to files:

  • docs/VCStatusCheckDesign.md
📚 Learning: 2026-01-16T02:31:35.817Z
Learnt from: jackjain
Repo: inji/mimoto PR: 995
File: docs/VCStatusCheckDesign.md:302-305
Timestamp: 2026-01-16T02:31:35.817Z
Learning: In the Inji Web/Mimoto system, all credentials are validated (schema and signature verification) before being added to the wallet. Therefore, any credentials existing in the database have already undergone validation, making it safe to set `is_schema_signature_valid` to `true` during migration scripts for existing records.

Applied to files:

  • docs/VCStatusCheckDesign.md
🪛 LanguageTool
docs/VCStatusCheckDesign.md

[grammar] ~9-~9: Use a hyphen to join words.
Context: ...rent status of the credential. ### High level user flow #### Flow : User lands ...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
docs/VCStatusCheckDesign.md

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)


312-312: Bare URL used

(MD034, no-bare-urls)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-maven-apitest-mimoto / maven-build
🔇 Additional comments (8)
docs/VCStatusCheckDesign.md (8)

11-60: Well-structured Flow 1 with clear status check logic.

The sequence diagram effectively shows the conditional logic for status list checks with cache availability. The handling of partial cache availability (line 17) and the cache timestamp for lastCheckedAt (line 16) are clearly documented.


62-114: Flow 2 correctly implements user-initiated status checks.

The real-time status check flow with issuer interaction and cache updates is well-designed. The error handling (lines 104-113) appropriately prevents database updates on failure while still providing user feedback.


116-166: Flow 3 credential addition logic is sound.

The sequence diagram correctly shows synchronous status verification during credential addition. The failure path (lines 162-165) appropriately blocks credential storage on validation failure, which aligns with the NOT NULL constraint on status_last_checked_at in the database schema.


170-208: API contract for fetching credentials is well-defined.

The response structure clearly maps to the database schema, and the field naming follows proper conventions (camelCase for API, snake_case for DB). The statusChecks array structure provides flexibility for multiple status purposes.


210-286: Comprehensive error handling in status check endpoint.

The API contract defines appropriate HTTP status codes and error responses for various failure scenarios (404, 400, 424, 500). The behavior notes (lines 282-285) clearly document the non-mutating nature of failed checks.


287-303: Database schema design is appropriate.

The schema additions support the required functionality with appropriate constraints. The is_expired nullable field is justified for migrated credentials (line 295), and the NOT NULL constraints on is_schema_signature_valid and status_last_checked_at align with the synchronous validation flow.

Based on learnings, the migration strategy correctly sets is_schema_signature_valid to true since all existing credentials were already validated during addition.


305-317: Caching strategy balances performance and freshness.

The 24-hour TTL (line 316) provides a reasonable trade-off between reducing issuer calls and maintaining status accuracy. The configurable TTL offers flexibility for different deployment requirements.


318-344: VC Verifier library modifications maintain backward compatibility.

The optional statusListCredentialCache parameter (line 331) allows existing functionality to remain unchanged when no cache is provided. The addition of statusListCredential to CredentialStatusResult (line 342) enables cache population without breaking existing callers.

Based on learnings, the singular naming of statusListCredential is correct since each result holds exactly one credential per status purpose.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Fix all issues with AI agents
In `@docs/VCStatusCheckDesign.md`:
- Line 300: The NOT NULL constraint on the status_last_checked_at column will
block inserting newly created credentials before an async status check; update
the schema or docs so insertion succeeds by either making status_last_checked_at
nullable or assigning a sensible default (e.g., set status_last_checked_at =
created_at) during credential creation, and clearly document the chosen behavior
in the VCStatusCheckDesign.md (referencing status_last_checked_at and the
credential creation flow/Flow 3) so implementers know whether the check is async
and when the column is populated.
- Line 66: The doc shows inconsistent lastCheckedAt semantics: Flow 1 sets
lastCheckedAt to the cache creation time while Flow 2 sets it to the current
time; pick a single authoritative behavior (either always set lastCheckedAt to
the actual check time or always use the cache creation timestamp) and update the
design text to standardize it (or explicitly document the intentional
difference). Update the sections referencing lastCheckedAt (the Flow 1
description that ties it to "cache creation time" and the Flow 2 description
that sets it to "current time") so both flows use the chosen convention and add
a brief note explaining the rationale and any impact on cache staleness or
auditability.
- Around line 341-345: The field naming is inconsistent: update the data class
CredentialStatusResult to reflect that multiple status list credentials may be
returned by renaming statusListCredential to statusListCredentials and changing
its type to List<JsonLDObject>? (or MutableList/Sequence as appropriate), then
update all references, usages and documentation (design text lines mentioning
"status list credential(s)" and "status list credential cache") to use the
plural name and iterate over the list where multiple lists are expected so
callers handle zero/one/many uniformly; alternatively, if you intend a
single-entry result, adjust the design text to explicitly state it's only one
credential and keep the singular name across code and docs.
- Line 297: The is_expired column should not be nullable: change the schema for
is_expired to NOT NULL with a sensible default (e.g., DEFAULT FALSE) and add a
migration to backfill existing NULL values (compute expiration from the
credential's expires_at or set FALSE if unknown); update any code paths that
create or refresh credentials to explicitly compute and set is_expired based on
current time and the credential expiry field so it remains deterministic;
alternatively, if NULL must be preserved for a documented state, add
documentation explaining exactly when is_expired can be NULL instead of changing
the schema.
- Around line 302-305: The migration currently sets
verifiable_credential.is_schema_signature_valid = true and
status_last_checked_at = now() for all rows which misrepresents unverified
credentials; change the migration to initialize is_schema_signature_valid to
NULL (or add a new enum/status value like "not_yet_verified") and set
status_last_checked_at = NULL, enqueue all credential IDs for asynchronous
verification via the existing status-check worker (or create a background job)
to update is_schema_signature_valid and status_last_checked_at when verified,
and update docs/UI to surface the "not_yet_verified" state so users know which
credentials have not been verified yet.
- Around line 155-162: The sequence diagram's Flow 3 contradictorily returns an
error and then proceeds to store the credential and show a success—fix by
treating "status list not applicable" as a normal (non-error) path: remove the
error-return and user-error steps (the lines where "Mimoto-->>InjiWeb: return
error" and "InjiWeb-->User: Show error message to the user") so the flow remains
Mimoto->>Database: Store credential (verifiable_credential table) ->
Database-->>Mimoto: Acknowledgement -> Mimoto-->>InjiWeb: Success ->
InjiWeb-->User: Show success message; ensure only the success branch stores the
credential and not the error branch.
🧹 Nitpick comments (5)
docs/VCStatusCheckDesign.md (5)

15-17: Clarify the cache availability requirement and its implications.

The design states that if the status list cache is missing or partially available, the status check will be skipped. Consider documenting:

  • What happens to the user experience when status checks are skipped?
  • Should there be a background job to populate missing cache entries?
  • How will users be informed that their credential status wasn't verified?

16-16: Clarify the "minimum time" logic for multiple status lists.

The statement "if there are multiple list involved then minimum time will be updated in the database" is ambiguous. Consider clarifying:

  • Why is the minimum time chosen rather than the maximum or the time of the most recent check?
  • Could this lead to confusion where lastCheckedAt doesn't reflect when some status lists were actually verified?

320-346: Clarify why statusListCredential is null when using cache.

Line 347 states: "The new field will be null when status list credential is fetched from cache or if its not applicable for the credential."

However, when the status list credential is fetched from cache, the actual credential data is available in the cache. Why not return it in CredentialStatusResult? This would:

  • Provide consistency regardless of cache hits/misses
  • Allow callers to access the status list credential without additional cache lookups
  • Simplify downstream logic

If there's a specific reason for this design choice (e.g., performance, avoiding duplication), please document it in the design.


318-318: Document the rationale for 24-hour cache TTL.

A 24-hour TTL for revocation status seems long from a security perspective, as credentials could remain accessible for up to a day after being revoked. While this may be acceptable for performance reasons, consider:

  • Documenting the security vs. performance trade-off
  • Noting whether this aligns with industry standards for VC status checking
  • Clarifying whether this TTL is appropriate for all status purposes (revocation, suspension, etc.)

9-9: Address documentation formatting issues.

Static analysis tools have identified minor formatting issues:

  1. Line 9: "High level" should be hyphenated as "high-level" when used as an adjective
  2. Line 5: Heading level jumps from h1 to h3, skipping h2 (should use ## instead of ###)
  3. Line 314: Bare URL should be enclosed in angle brackets or proper markdown link syntax

These are minor documentation quality issues that improve readability.

📝 Proposed formatting fixes
-### Overview
+## Overview

-### High level user flow
+### High-level user flow

-- **Value**:
-  - `statusListCredential`: The actual bitstring retrieved from the status list credential
+- **Value**:
+  - `statusListCredential`: The actual bitstring retrieved from the status list credential (e.g., <https://injicertify-farmer.dev-int-inji.mosip.net/v1/certify/credentials/status-list/a7b3ac9a-861a-4fa3-9c85-27e79d35fad3>)

Also applies to: 5-5, 314-314

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84f1790 and d96b961.

📒 Files selected for processing (1)
  • docs/VCStatusCheckDesign.md
🧰 Additional context used
🪛 LanguageTool
docs/VCStatusCheckDesign.md

[grammar] ~9-~9: Use a hyphen to join words.
Context: ...rent status of the credential. ### High level user flow #### Flow : User lands ...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
docs/VCStatusCheckDesign.md

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)


314-314: Bare URL used

(MD034, no-bare-urls)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-maven-apitest-mimoto / maven-build

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant