@assembly-js/app-foundation 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -19,6 +19,12 @@ A patch release never changes what an app's build requires; a minor release may
19
19
  not by hand; see `changes/README.md`. CI fails a PR that changes a check script without a
20
20
  `bump: minor` change file.
21
21
 
22
+ ## 0.7.2
23
+ - [guidance] The build agent now sets `allow="autoplay; fullscreen; picture-in-picture; encrypted-media"` and `allowfullscreen` on embedded video player iframes, so Vimeo and YouTube players can go fullscreen, autoplay and use picture-in-picture inside the portal.
24
+
25
+ ## 0.7.1
26
+ - [fix] The location reporter no longer sends the host's embed-session params (`token`, `clientId`, `companyId`) with the app's location, so they never reach the host URL or a copied deep link.
27
+
22
28
  ## 0.7.0
23
29
  - [new] `deleteFile(key)` in `@assembly-js/app-foundation/server` permanently deletes a file stored with app-storage.
24
30
  - [guidance] The assembly-storage skill documents `deleteFile`: deletion is permanent, so apps that want recovery hide the record first and delete the file later.
package/CLAUDE.md CHANGED
@@ -474,6 +474,7 @@ Because the app runs in an iframe inside the parent dashboard, several normal Ne
474
474
  - **Cookies must be `sameSite: 'none'` and `secure: true`.** Anything else is dropped silently in cross-origin iframes.
475
475
  - **No top-level navigation.** Don't use `window.location = '...'` to go to external URLs — it'll either break out of the iframe or be blocked. For external links use `<a target="_blank" rel="noreferrer">`.
476
476
  - **No `window.open(..., '_self')`.** Same issue.
477
+ - **Nested video players re-delegate their permissions.** When you embed a Vimeo, YouTube or similar player in an `<iframe>`, set `allow="autoplay; fullscreen; picture-in-picture; encrypted-media"` and `allowfullscreen` on that iframe. Permissions pass down one frame at a time: the portal grants them to your app, but the player only gets them if your iframe grants them again, so without the attribute fullscreen, picture-in-picture and DRM playback fail silently.
477
478
  <!-- !feature:app-owned-header -->
478
479
  - **The portal owns the chrome (header, sidebar).** Don't render your own breadcrumbs or page titles via DOM. Use `@assembly-js/app-bridge` to set them.
479
480
  - **Never put the app name in breadcrumbs.** The parent portal *automatically* prepends the app's name as breadcrumb 0. If you also pass `{ label: 'MyApp' }` as the first entry of `setBreadcrumbs`, it renders twice ("MyApp / MyApp / Reports"). For a flat one-page app pass `[]` (or skip `setBreadcrumbs` entirely). For a multi-level app pass only the sub-pages: `setBreadcrumbs([{ label: 'Reports' }, { label: 'Q4 2026' }])`. Read `.claude/skills/assembly-app-bridge-header/SKILL.md` for full examples.
@@ -1,3 +1,9 @@
1
+ export declare const HOST_SESSION_PARAMS: string[];
2
+ /**
3
+ * The app's own query string with the host's embed-session params removed,
4
+ * as a `?`-prefixed string, or '' when nothing is left.
5
+ */
6
+ export declare function stripHostSessionParams(searchParams: URLSearchParams): string;
1
7
  export declare function getSurfacePrefixes(): string[];
2
8
  export declare const SURFACE_PREFIXES: string[];
3
9
  /**
@@ -1,4 +1,19 @@
1
1
  const DEFAULT_PREFIXES = ['/c', '/n'];
2
+ // The host puts these on the iframe src to open the embed session. They are
3
+ // not part of the app's location, and reporting them would put the token in
4
+ // the host URL, browser history and every copied deep link.
5
+ export const HOST_SESSION_PARAMS = ['token', 'clientId', 'companyId'];
6
+ /**
7
+ * The app's own query string with the host's embed-session params removed,
8
+ * as a `?`-prefixed string, or '' when nothing is left.
9
+ */
10
+ export function stripHostSessionParams(searchParams) {
11
+ const own = new URLSearchParams(searchParams);
12
+ for (const key of HOST_SESSION_PARAMS)
13
+ own.delete(key);
14
+ const qs = own.toString();
15
+ return qs ? `?${qs}` : '';
16
+ }
2
17
  // Read surface prefixes from the build-time env value injected by withAssemblyDev.
3
18
  // Falls back to the historical /c and /n defaults so apps on an older image
4
19
  // continue to work without a rebuild.
@@ -2,7 +2,7 @@
2
2
  import { Suspense, createElement, useEffect, useRef } from 'react';
3
3
  import { usePathname, useSearchParams, useRouter } from 'next/navigation';
4
4
  import { AssemblyBridge } from '@assembly-js/app-bridge';
5
- import { getSurfacePrefix, stripPrefix, addPrefix } from './location-prefix.js';
5
+ import { getSurfacePrefix, stripPrefix, addPrefix, stripHostSessionParams } from './location-prefix.js';
6
6
  function LocationReporterInner() {
7
7
  const pathname = usePathname();
8
8
  const searchParams = useSearchParams();
@@ -19,8 +19,7 @@ function LocationReporterInner() {
19
19
  if (!bridgeLocation)
20
20
  return;
21
21
  const path = stripPrefix(pathname, prefix);
22
- const qs = searchParams.toString();
23
- bridgeLocation.report(path, qs ? `?${qs}` : '');
22
+ bridgeLocation.report(path, stripHostSessionParams(searchParams));
24
23
  }, [bridgeLocation, pathname, searchParams, prefix]);
25
24
  // Register the navigate handler once; rely on prefixRef for the current prefix.
26
25
  useEffect(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assembly-js/app-foundation",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Versioned foundation helpers and build context for Assembly generated apps",
5
5
  "type": "module",
6
6
  "files": [