Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "proxy-smart-backend",
"displayName": "Proxy Smart Backend",
"version": "0.3.16-beta.202608161203.54bbcfc20",
"version": "0.3.16-alpha.202608161355.6a472910c",
"type": "module",
"scripts": {
"test": "bun test --isolate",
Expand Down
25 changes: 7 additions & 18 deletions backend/src/lib/shl-scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,32 +197,21 @@ interface FhirBundleLike {
}

/**
* The `query` hints for this share — the SHL spec's optional field on
* `application/smart-api-access`, "hints to the client, indicating queries it
* might want to make".
* The SHL spec's `query` hints. Carries the identifier filter `scopeFhirRequest`
* forces, so what the recipient is told to run is what will be allowed.
*
* A study-scoped link has no other way to say what it is about, so a recipient
* fires its usual sweep and the default-deny proxy rejects nearly all of it. The
* hint carries the same identifier filter `scopeFhirRequest` forces, so what the
* recipient is told to run is exactly what will be allowed.
*
* Whole-patient shares get no hints on purpose. Listing the reachable types would
* name the withheld ones by omission, which is more than the patient agreed to
* disclose.
* Whole-patient shares get none: naming the reachable types names the withheld
* ones by omission.
*/
export function shareQueryHints(narrowing: { studyInstanceUID?: string }): string[] | undefined {
if (!narrowing.studyInstanceUID) return undefined
return [`ImagingStudy?identifier=urn:oid:${narrowing.studyInstanceUID}`]
}

/**
* True only when NOTHING narrows the share.
*
* @deprecated Conflates the two narrowings it counts: a study-scoped link and a
* de-selected record both report `false`, which reads as a warning for one and as
* the definition of the link for the other. Recipients should use the `query`
* hints for what the share covers and `maxhealth_records_withheld` for what was
* held back. Kept until both viewers ship those.
* True only when NOTHING narrows the share. Sound as an affirmation only: `false`
* covers both a study-scoped link and a de-selected record, which mean opposite
* things to a reader. Act on `true`; use the `query` hints for anything else.
*/
export function isCompleteShare(narrowing: {
selectiveScope?: SelectiveScope
Expand Down
4 changes: 1 addition & 3 deletions backend/src/routes/api/shl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,7 @@ export function buildSmartApiAccess(session: {
aud: `${config.baseUrl}/api/shl/fhir`,
// Spec field. Undefined drops out of the JSON, which is the "no hints" case.
query: shareQueryHints({ studyInstanceUID: session.studyInstanceUID }),
// Ours, and named so: nothing in the SHL spec describes a withheld record.
maxhealth_records_withheld: isSelectiveScopeActive(selectiveScope),
// Deprecated — see isCompleteShare. Emitted until both viewers read the above.
// Ours. Only `true` carries meaning — see isCompleteShare.
complete: isCompleteShare({
selectiveScope,
studyInstanceUID: session.studyInstanceUID,
Expand Down
20 changes: 0 additions & 20 deletions backend/test/shl-access-document.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,6 @@ describe('buildSmartApiAccess — query hints', () => {
})
})

describe('buildSmartApiAccess — withheld records', () => {
it('reports nothing withheld from a whole-patient share', () => {
expect(parse(buildSmartApiAccess(base)).maxhealth_records_withheld).toBe(false)
})

it('reports records withheld when the patient de-selected some', () => {
const doc = parse(buildSmartApiAccess({
...base,
shareScope: { excludedTypes: ['Condition'], excludedIds: [], excludedObservationCategories: [] },
}))
expect(doc.maxhealth_records_withheld).toBe(true)
})

/** Study scoping is not withholding — it is what the link is for. */
it('reports nothing withheld from a study-scoped share', () => {
const doc = parse(buildSmartApiAccess({ ...base, studyInstanceUID: '1.2.840.113619.2.55.3' }))
expect(doc.maxhealth_records_withheld).toBe(false)
})
})

describe('buildSmartApiAccess', () => {
it('reports a whole-patient share as complete', () => {
expect(parse(buildSmartApiAccess(base)).complete).toBe(true)
Expand Down
2 changes: 1 addition & 1 deletion deploy/infra/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "proxy-smart-infra",
"displayName": "Proxy Smart Infrastructure",
"description": "AWS CDK infrastructure for Proxy Smart production deployment",
"version": "0.3.16-beta.202608161203.54bbcfc20",
"version": "0.3.16-alpha.202608161355.6a472910c",
"private": true,
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "proxy-smart",
"version": "0.3.16-beta.202608161203.54bbcfc20",
"version": "0.3.16-alpha.202608161355.6a472910c",
"repository": {
"type": "git",
"url": "git+https://github.com/Max-Health-Inc/proxy-smart.git"
Expand Down
2 changes: 1 addition & 1 deletion scripts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "proxy-smart-scripts",
"version": "0.3.16-beta.202608161203.54bbcfc20",
"version": "0.3.16-alpha.202608161355.6a472910c",
"description": "CI/CD and development scripts for Proxy Smart",
"private": true,
"type": "module",
Expand Down