Add Method 1 (fetch by request_id) for self/current-session data + fix latest-consent-anchor drift bug

- M3HiuWorkflowService: data_fetch now supports fetch_by_request_id=1, sending request_id (not consent_id) per bridge Method 1 -- targets the current/self consent request's own session, distinct from Method 2 (consent_id, which can resolve to a stale session sharing the same artifact).
- Patient::abdm_content_fetch_only(): tries Method 2 (consent_id) -> Method 1 (request_id, self data) -> Method 3 (abha_address, historical fallback) in order, stopping as soon as real documents are found.
- Fixed a real pre-existing bug this surfaced: getLatestAbdmSyncSnapshot() used the same flawed 'status=SUCCESS implies COMPLETED' check (without requiring workflow_state=DATA_RECEIVED) already fixed elsewhere in computeConsentSessionDetail(). This let broad/historical data_fetch rows (status=success, but decrypted_data=[]) hijack priority-500 'best' selection and silently drift the resolved 'latest granted consent' to an unrelated historical consent_id after Method 3 fallback ran. Now requires workflow_state=DATA_RECEIVED, matching the earlier fix.
This commit is contained in:
DevSoftTech Server 2026-07-29 02:31:29 +05:30
parent c87928c2bc
commit ad98afbe57
2 changed files with 72 additions and 1 deletions

View File

@ -2070,6 +2070,39 @@ class Patient extends BaseController
$documentsPersisted = (int) ($fetchResult['documents_persisted'] ?? 0);
$documentsUpdated = (int) ($fetchResult['documents_updated'] ?? 0);
// The consent-artifact-scoped fetch above (bridge "Method 2") may resolve
// to a stale/different session sharing the same consent artifact id. Per
// the bridge gateway team, GET /v1/hiu/data/fetch?request_id=... ("Method
// 1") targets the ONE specific consent request instead -- this is the
// "self"/current session's own data. Try it before falling back to the
// broader by-ABHA-address historical lookup (Method 3).
if ($documentsPersisted + $documentsUpdated === 0 && $consentRequestRef !== '') {
try {
$requestIdFetchResult = $service->runOperation('data_fetch', [
'abha_address' => $abhaContext['abha_address'],
'consentRequestId' => $consentRequestRef,
'fetch_by_request_id' => 1,
]);
} catch (\Throwable $e) {
$requestIdFetchResult = null;
}
if (is_array($requestIdFetchResult) && (int) ($requestIdFetchResult['ok'] ?? 0) === 1) {
$reqDocumentsPersisted = (int) ($requestIdFetchResult['documents_persisted'] ?? 0);
$reqDocumentsUpdated = (int) ($requestIdFetchResult['documents_updated'] ?? 0);
if ($reqDocumentsPersisted + $reqDocumentsUpdated > 0) {
return $this->response->setJSON([
'ok' => 1,
'phase' => 'COMPLETED',
'message' => 'Records fetched successfully using existing granted consent.',
'documents_persisted' => $reqDocumentsPersisted,
'documents_updated' => $reqDocumentsUpdated,
'data' => ['data_fetch' => $fetchResult, 'data_fetch_by_request_id' => $requestIdFetchResult],
]);
}
}
}
// The consent-artifact-scoped fetch above (bridge "Method 1/2") only
// returns data for the ONE consent/request we targeted. Per the bridge
// gateway team, GET /v1/hiu/data/fetch?abha_address=... ("Method 3")
@ -3552,7 +3585,16 @@ class Patient extends BaseController
$phase = 'REQUESTED';
$priority = 120;
if (($operation === 'DATA_FETCH' || $operation === 'HI_DATA_PUSH_CALLBACK') && $status === 'SUCCESS') {
// NOTE: `status` only reflects whether the bridge API call itself
// succeeded (no HTTP/transport error) -- it does NOT mean the HIP
// actually sent any health records (see M3HiuWorkflowService::
// resolveState()/runOperation(), which always set status=success for
// any error-free response, even one reporting decrypted_data=[]).
// Whether data truly arrived is tracked separately via workflow_state
// (DATA_PENDING vs DATA_RECEIVED); require that here too, otherwise a
// broad/historical data_fetch attempt with empty decrypted_data can
// wrongly hijack "latest consent" resolution with a stale consent_id.
if (($operation === 'DATA_FETCH' || $operation === 'HI_DATA_PUSH_CALLBACK') && $status === 'SUCCESS' && $state === 'DATA_RECEIVED') {
$phase = 'COMPLETED';
$priority = 500;
} elseif (in_array($rawConsentStatus, ['GRANTED', 'APPROVED', 'ACTIVE'], true)) {

View File

@ -998,6 +998,35 @@ class M3HiuWorkflowService
];
}
// Method 1 (per bridge gateway team, 2026-07-29): GET /v1/hiu/data/fetch
// ?request_id=... fetches data for the ONE specific consent request that
// request_id belongs to -- this is the "self"/current session's own data,
// distinct from Method 2 (consent_id, which can resolve to a different/
// stale session sharing the same consent artifact) and Method 3 (abha_address,
// which returns unrelated historical sessions across every past consent).
// Callers opt in explicitly via fetch_by_request_id=1.
$fetchByRequestId = (int) ($clean['fetch_by_request_id'] ?? 0) === 1;
if ($fetchByRequestId) {
$requestIdOnly = trim((string) (
$clean['abdm_consent_request_id']
?? $clean['consentRequestId']
?? $clean['consent_request_id']
?? ''
));
if ($requestIdOnly === '') {
return [
'ok' => 0,
'http_code' => 422,
'error_text' => 'consent_request_id is required to fetch data by request_id (Method 1).',
];
}
return [
'ok' => 1,
'payload' => ['request_id' => $requestIdOnly],
];
}
$requestFallback = '';
if (! $requestIdGenerated) {
$requestFallback = trim((string) (