Skip to content

Commit 5d54a23

Browse files
Merge pull request #1021 from Max-Health-Inc/develop
🧪 Auto-PR: Merge `develop` → `test`
2 parents 10617b9 + 4378121 commit 5d54a23

16 files changed

Lines changed: 61 additions & 14 deletions

File tree

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "proxy-smart-backend",
33
"displayName": "Proxy Smart Backend",
4-
"version": "0.3.14-beta.202608131946.961ab42c4",
4+
"version": "0.3.15-alpha.202608132031.ec7491a2e",
55
"type": "module",
66
"scripts": {
77
"test": "bun test --isolate",

backend/src/lib/shl-scope.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,24 @@ interface FhirBundleLike {
196196
[key: string]: unknown
197197
}
198198

199+
/**
200+
* True only when NOTHING narrows the share.
201+
*
202+
* The recipient is told "complete summary — the patient shared their full health
203+
* record" on the strength of this, so every dimension that narrows a share has to
204+
* be counted here. It lives beside the scope rules rather than inline at the mint
205+
* site because that is how it drifted: it knew about selective de-selection and
206+
* not about study scoping, so a single-study link claimed to carry everything
207+
* while the proxy answered almost every query with 403 — which the viewer drew as
208+
* "no allergies, no medications, no conditions".
209+
*/
210+
export function isCompleteShare(narrowing: {
211+
selectiveScope?: unknown
212+
studyInstanceUID?: string
213+
}): boolean {
214+
return !narrowing.selectiveScope && !narrowing.studyInstanceUID
215+
}
216+
199217
/** True when the scope actually narrows anything (else all helpers are no-ops). */
200218
export function isSelectiveScopeActive(scope: SelectiveScope): boolean {
201219
return (

backend/src/routes/api/shl.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { shlSessionStore, type ShareScope, type ShlSession } from '@/lib/shl-ses
3434
import {
3535
isDicomPathAllowed,
3636
scopeFhirRequest,
37+
isCompleteShare,
3738
isSelectiveScopeActive,
3839
preScreenSelectiveRequest,
3940
applySelectiveFilter,
@@ -449,7 +450,7 @@ export const shlRoutes = new Elysia({ prefix: '/shl', tags: ['shl'] })
449450
scope: 'patient/*.read',
450451
patient: patientId,
451452
aud: `${config.baseUrl}/api/shl/fhir`,
452-
complete: !shareScope,
453+
complete: isCompleteShare({ selectiveScope: shareScope, studyInstanceUID: body.studyInstanceUID }),
453454
})
454455

455456
// Generate SHL using kill-the-clipboard

backend/test/shl-scope.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// SPDX-FileCopyrightText: Max Health Inc.
2+
// SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Commercial
3+
14
/**
25
* SHL Scope Enforcement — unit tests for the pure access-control decisions.
36
*
@@ -10,6 +13,7 @@ import { describe, expect, it } from 'bun:test'
1013
import {
1114
isDicomPathAllowed,
1215
scopeFhirRequest,
16+
isCompleteShare,
1317
isSelectiveScopeActive,
1418
preScreenSelectiveRequest,
1519
applySelectiveFilter,
@@ -286,3 +290,27 @@ describe('emptySearchBundle', () => {
286290
expect(emptySearchBundle()).toEqual({ resourceType: 'Bundle', type: 'searchset', total: 0, entry: [] })
287291
})
288292
})
293+
294+
describe('isCompleteShare — what the recipient is told the link carries', () => {
295+
it('is complete when nothing narrows the share', () => {
296+
expect(isCompleteShare({})).toBe(true)
297+
expect(isCompleteShare({ selectiveScope: undefined, studyInstanceUID: undefined })).toBe(true)
298+
})
299+
300+
it('is NOT complete when the patient de-selected records', () => {
301+
expect(isCompleteShare({ selectiveScope: { excludedTypes: ['Condition'] } })).toBe(false)
302+
})
303+
304+
/**
305+
* The regression: a study-scoped link reported `complete: true`, so the viewer
306+
* showed "the patient shared their full health record" over a record whose every
307+
* other query the proxy answers with 403.
308+
*/
309+
it('is NOT complete when the share is scoped to a single imaging study', () => {
310+
expect(isCompleteShare({ studyInstanceUID: STUDY })).toBe(false)
311+
})
312+
313+
it('is NOT complete when both narrowings apply', () => {
314+
expect(isCompleteShare({ selectiveScope: { excludedTypes: ['Condition'] }, studyInstanceUID: STUDY })).toBe(false)
315+
})
316+
})

config/eslint/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@proxy-smart/eslint-config",
3-
"version": "0.3.14-beta.202608131924.cfdc0c7f7",
3+
"version": "0.3.14-beta.202608131946.961ab42c4",
44
"private": true,
55
"type": "module",
66
"exports": {

deploy/infra/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "proxy-smart-infra",
33
"displayName": "Proxy Smart Infrastructure",
44
"description": "AWS CDK infrastructure for Proxy Smart production deployment",
5-
"version": "0.3.14-beta.202608131946.961ab42c4",
5+
"version": "0.3.15-alpha.202608132031.ec7491a2e",
66
"private": true,
77
"type": "module",
88
"scripts": {

frontend/smart-dicom-template/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "SMART DICOM Algorithm Template",
44
"description": "Starter kit for building SMART on FHIR imaging algorithm apps. Clone, implement your algorithm in src/algorithm.ts, and deploy as a SMART app.",
55
"private": true,
6-
"version": "0.3.14-beta.202608131924.cfdc0c7f7",
6+
"version": "0.3.14-beta.202608131946.961ab42c4",
77
"type": "module",
88
"scripts": {
99
"dev": "vite --port 5180",

frontend/ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "Proxy Smart Admin UI",
44
"description": "A web-based administration interface for managing healthcare applications and resources via Proxy Smart.",
55
"private": true,
6-
"version": "0.3.14-beta.202608131924.cfdc0c7f7",
6+
"version": "0.3.14-beta.202608131946.961ab42c4",
77
"type": "module",
88
"scripts": {
99
"dev": "vite",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "proxy-smart",
3-
"version": "0.3.14-beta.202608131946.961ab42c4",
3+
"version": "0.3.15-alpha.202608132031.ec7491a2e",
44
"repository": {
55
"type": "git",
66
"url": "git+https://github.com/Max-Health-Inc/proxy-smart.git"

packages/app-store/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@proxy-smart/app-store",
3-
"version": "0.3.14-beta.202608131924.cfdc0c7f7",
3+
"version": "0.3.14-beta.202608131946.961ab42c4",
44
"private": false,
55
"type": "module",
66
"description": "SMART on FHIR app store — manifest discovery, visibility configuration, and registry CRUD. Framework-agnostic.",

0 commit comments

Comments
 (0)