ORION App SDK 1.6.0
Build and upload a runnable app for ORION's App Store, without public hosting. This kit contains the complete supported SDK v1 contract, ready-to-import JavaScript, TypeScript types, manifest tools, starters, a local host and publication guidance.
SDK v1 shares display context. SDK 1.2 also supports brokered actions with per-action member approval: selected Work Suite files, new private documents, basic display identity, clipboard copy, window notices and native-app navigation. It never exposes ORION session tokens, UCI tokens, database keys or policy administration. Read Actions and approval before requesting scopes.
Start here
• Extract the ZIP. Open a terminal in the orion-app-sdk folder.
• Use Node.js 20 or newer. Run npm run dev (no install needed).
• Open http://localhost:4173. Test light/dark and organization sharing.
• Edit examples/vanilla, or create a project with
node bin/orion-app.mjs create my-app.
• Replace the example publisher/ID and submission metadata. The starter uses
ORION's public host-origin bootstrap when running as an uploaded package.
• Run npm install in the SDK folder, then node bin/orion-app.mjs bundle my-app.
Upload the resulting .orion-app file in My apps. No hosting is needed.
• Validate with node bin/orion-app.mjs validate examples/vanilla/orion.manifest.json.
• Follow Submission & lifecycle. Downloads do not install
or approve an app. A curator reviews apps; members with App Store access install them personally. Native-app permissions and per-action consent govern SDK actions.
The local host uses synthetic records and two loopback ports, 4173 and 4174. Close it with Ctrl+C. It never contacts ORION or needs credentials.
Use the library
In a bundler project, npm install /path/to/extracted/orion-app-sdk and import:
import {connectOrionHost} from '@orionos/app-sdk'
const disconnect = connectOrionHost('https://www.orionos.app', context => {
// Only use public display context. Keep identity and authorization separate.
console.log(context.organization?.name)
})
// Call disconnect() when unmounting your app.
For plain browser JavaScript, import dist/index.js directly. All dist files must remain together; the library has no runtime dependencies. The browser bridge remains dependency-free. The local packager uses pinned esbuild and parse5. The SDK is distributed as a ZIP/local package, not a published npm package. See Upload without hosting for the full journey.
Guide
• Architecture & supported capabilities
• Bridge API & message protocol
• Submission, review & updates
• Native platform contributions
Checks
npm test runs the packaged bridge, origin-validation and manifest tests. To rebuild dist after editing TypeScript: npm install, then npm run build. The included compiler version is pinned; generated output ships in the ZIP.
SDK 1.6.0 is the kit version. sdkVersion: 1 is the protocol. ORION 4.16.0 is the verified hosted baseline. Older v1 hosts support the initial on-load message; updated hosts also support ready handshakes and live theme changes. Use the current ORION web release or update the installed desktop program for the full submission interface.
The local host also includes tablet and phone preview widths. Test keyboard navigation, small screens, and standalone behavior before submitting an app. Connection availability is display context only; see the lifecycle options in docs/api.md.
Protect unfinished work
SDK 1.3 supports registered drafts in ORION 4.14. See Drafts and closing for host negotiation, timeouts and the runnable example.
Developer workflow
See Submission & lifecycle. Generate a vanilla or React project, build it locally and run bundle. Import the runnable .orion-app in App Store → Developers → My apps. Save to screen and store its bytes, preview with synthetic data, then submit. External HTTPS apps can still use check and package with hosting verification. Follow decisions and publish updates from the same workspace.
Custom app artwork is supported in the reviewed manifest. Both starters include original example PNG artwork. Use orion-app icon <project-folder> <artwork.png> and follow the Design & accessibility guide.
Actions and approval
SDK 1.2 adds six brokered actions. Declare each required scope in the manifest before review. Installation is personal; it is not a grant of private data or native ORION authority. Existing theme-only apps keep working unchanged.
| Scope | Method | Member decision and limits |
|---|---|---|
profile.basic | profile.read | Allow once to share name and callsign; no email, rank, account ID, credentials or UCI token |
documents.read.selected | documents.open | Choose one owned Write, Grid or Present file in ORION's picker; no directory listing is sent to the app |
documents.create | documents.create | Review content and create a new private Work Suite file; cannot overwrite, delete or change sharing |
clipboard.write | clipboard.write | Review up to 20,000 characters and copy once; cannot read clipboard |
notifications.show | notifications.show | Approve a notice of up to 280 characters inside this app's window; cannot broadcast to members |
shell.open | shell.open | Open Write, Grid, Present, Calendar, My Work or Link Library with the member's current permissions |
Client usage
import {createOrionClient} from './sdk/index.js'
const client = createOrionClient('https://www.orionos.app', {
onStatus: status => { /* Enable action buttons only when connected. */ },
onContext: context => { /* Match appearance; this is not identity proof. */ }
})
// From your app's explicit action button, after the host connects:
const file = await client.request('documents.open', {kind:'write'})
const saved = await client.request('documents.create', {
kind:'write', title:'Prepared brief', body:{text:'Your prepared content'}
})
// Call client.disconnect() when unmounting or leaving the app.
request returns a typed result or rejects with a member decline, unavailable permission, expired approval or other error. Show that error where the member took the action. Do not automatically retry: a write's outcome may be uncertain. The client allows one pending request, waits up to 125 seconds and rejects outstanding requests on disconnect. No session token is exposed.
How approval works
The app sends a fresh UUID request ID, method and parameters to the exact ORION parent origin with the launch nonce. ORION checks the sending origin and frame, reviewed manifest, personal installation, organization block and current member permissions. A trusted ORION dialog shows the app, publisher, origin and precise action or file choice. Only the member can approve that dialog.
An approval is bound to the member, organization, app, reviewed manifest, launch, method and a digest of the parameters. It expires in two minutes and can be used once. All server checks run again at execution. Work Suite access also requires the corresponding native app permission and, for Corp, a current work-space affiliation. A chosen file is read again at approval and must still belong to the member. Shared organizational files are outside this version's picker.
There are 12 prepared actions per minute and 200 per day per member, organization and app, across all launches. Excess requests create a review flag. Unsupported declared-scope requests are denied and flagged, with duplicate flags coalesced. A single frame handles one approval at a time and at most 1,000 distinct request IDs per launch. Messages and file contents are bounded to 300 KB. An app may send requests only through the bridge; there is no general API proxy.
Oversight and revocation
Members report concerns through About this app → Report a concern. Staff use Policy Management → App safety. Organization policy administrators can block an app locally, inspect activity and resolve reports. Only the platform curator can approve, suspend globally or retire an app. A reason is required and recorded for every review decision. Reports are limited to five per hour per member.
Suspension and organization blocks deny new launches and requests immediately. Running windows close on their next successful access refresh, normally within 30 seconds. An operation already being processed may finish. Unblocking preserves personal installation choices; retirement removes installations and pending approvals. A changed manifest requires retirement, a new draft and review, then members install again. Every action still needs a fresh member approval.
Activity logs contain method, decision and outcome metadata, not document bodies, clipboard text or credentials. Transient approval records retain digests only, for at most one day when the app is next used. Normal/resolved activity older than 90 days is cleaned on subsequent use; unresolved reports and flags are retained. Publishers must disclose their own retention and deletion practices: once a member shares a file, ORION cannot recall copies on the publisher's service.
Boundaries
No SDK scope grants arbitrary HTTP proxying, SQL, database credentials, role or policy administration, bulk personnel access, personnel-status changes, financial transfers or native desktop execution. A member's OPE Admin level never becomes an SDK app's administrative authority. Private-data sharing requires deliberate approval even for an administrator.
The local development host demonstrates display context only. For action tests, use a reviewed app in a test organization with synthetic files. Do not test new scopes against real member records. Older hosts reject or time out on actions; handle unavailability and keep the app usable without the integration.
Library API
connectOrionHost(origin, onContext, options?) → disconnect
Registers a listener before sending orion:ready to window.parent. Only messages from that exact parent Window and exact configured origin are accepted. Calls onContext for valid orion:init messages, including later theme updates. Returns a cleanup function. Outside a browser it returns a no-op after validating the origin; it does not access browser globals during server rendering.
origin must be an HTTPS origin with no path or trailing slash, for example https://www.orionos.app. Apex and www origins differ. Select your deployment origin from developer-controlled configuration. Do not use arbitrary URL query parameters, message data or document.referrer to establish trust.
options.allowLocalhost=true permits HTTP only for loopback hosts during local development. Do not ship this option enabled in a hosted app. The production manifest validator always requires an external HTTPS launch URL.
interface OrionHostContextV1 {
channel: 'orion-app-sdk-v1'
type: 'orion:init'
nonce: string
theme: 'light' | 'dark'
organization: { slug: string; name: string } | null
capabilities: OrionCapability[]
}
The nonce identifies a host launch, not a user. It is not a secret or an access token. Treat subsequent valid context as updated display information. Unmounting and remounting the iframe creates a new launch. Organization switching is handled by ORION's normal workspace navigation, not an SDK method.
parseHostContext(value) → context | null
Validates protocol, message type, nonce length, appearance, capabilities and bounded organization strings. Drops fields outside the contract. This function validates shape only; connectOrionHost performs sender validation.
validateHostOrigin(origin, options?) → origin
Throws for an invalid origin. Use it to validate configuration before rendering a connection UI.
parseManifest(value) → manifest | null
Uses the same production validator as the App Store. It returns a normalized manifest or null. safeLaunchUrl(value) validates/normalizes only a launch URL. The CLI invokes this exact validator. A JSON Schema is included for editor help, but the production validator is authoritative for URL restrictions.
Wire protocol
App → host: {channel:'orion-app-sdk-v1',type:'orion:ready'}. Host → app: the OrionHostContextV1 object above. The host also sends context after iframe load for compatibility with existing v1 apps.
There are no other SDK methods or requests in v1. fetch('/api/...') inside your app reaches your own server; it is not an ORION data bridge. Do not make an app depend on undocumented platform endpoints, cookies or localStorage keys.
Connection lifecycle (SDK 1.1)
The 1.1 connection reports standalone, connecting, connected and unavailable through options.onStatus. It retries readiness for up to options.timeoutMs (1000–30000 ms, default 10000), accepts a late valid host, and pins the first accepted launch nonce. Call the returned cleanup function on unmount; reconnect after a back-forward-cache restoration if you disconnect on pagehide.
Brokered actions (SDK 1.2)
Use createOrionClient and typed request(method, params) for actions. See Actions and approval for methods, scope names, result types and failure handling.
Drafts and closing a window — SDK 1.3
ORION 4.14 adds window-local draft protection. It does not grant another data scope or permit background actions. The host displays and owns all close dialogs.
Use createOrionClient(origin, {onSave}) and call client.setDraft(true) as soon as there are unfinished changes. Call setDraft(false) only after the current work has actually been saved. No draft text or user identity is transmitted.
setDraft returns whether the connected host supports this protection. The host context includes lifecycleVersion: 1 when supported. If absent, tell the member to save before closing; do not claim the window is protected. Earlier SDK apps continue working, but gain no automatic knowledge of their own unsaved changes.
const client = createOrionClient(trustedHostOrigin, {
onContext(context) {
setHostProtectsDrafts(context.lifecycleVersion === 1)
},
async onSave() {
const snapshot = currentRevision
await saveToYourOwnService()
return snapshot === currentRevision // false if new edits arrived
},
})
// On editing:
client.setDraft(true)
// On a successfully confirmed save of the current revision:
client.setDraft(false)
// On unmount:
client.disconnect()
The member can choose Save, Don't Save or Cancel in trusted host UI. Hosts wait up to ten seconds for a matching save acknowledgment. Failure or timeout leaves the window open and allows cancellation or an explicit discard decision. An app cannot prevent a member from discarding its own draft indefinitely.
An onSave callback must finish without opening a new ORION approval dialog. The SDK rejects brokered requests during this callback and declines close-save while another approval is pending. If saving requires documents.create or another member-approved action, provide the explicit Save/Export button inside your app and omit onSave. The member can return to the app, approve the action, then close. Do not silently retry a timed-out or uncertain creation request.
This contract protects ORION window close, supported internal reload and the native restart flow. It does not prevent a page inside your own iframe from navigating away, a process crash, power loss or an externally forced termination. Implement your own consent-aware recovery if required, without storing ORION tokens or private selected files persistently by default.
The runnable examples/drafts/ sample demonstrates the lifecycle with a short local practice note. It contains no ORION records. Run npm run dev and open the Draft example from the local test host to exercise its save acknowledgment.
Architecture
ORION App Store hosts approved external web apps in a sandboxed iframe. Apps may be uploaded and hosted by ORION, or remain on an existing independent HTTPS origin. The host and app communicate using postMessage with exact target origins and sender-window checks.
Developer's app + backend (separate HTTPS origin)
↑ display context and approved one-use actions
ORION isolated host → reviewed manifest → personal install → current OPE + one-use member approval
Supported capabilities
| Capability | Supplied value | Permitted use |
|---|---|---|
theme | light or dark | Match the user's appearance |
organization.public | Public organization name and slug, or null | Display the workspace's label |
An empty capabilities list is valid. Do not apply the theme unless theme is listed. Do not infer membership, a tenant database or an account from a slug. Context contains no user ID or roles. An app can function standalone when no host sends context; show a useful fallback rather than a blank loading screen.
The six additional brokered scopes and their exact limits are described in Actions and approval. No action inherits the member’s full authority.
Host sandbox
Production uses allow-scripts allow-forms allow-same-origin, with referrerPolicy="no-referrer". Apps cannot navigate the top window or create popups through the sandbox. The same-origin flag permits the app's own storage where the browser permits it; it does not put the app on ORION's origin. Do not rely on third-party cookies. Permissions for camera, microphone, downloads and native desktop APIs are not part of SDK v1.
Never serve a third-party app from ORION's own origin. Never inject its code into the shell. ORION verifies a separate origin again at launch.
For the recommended ORION-hosted format, see Upload without hosting. Uploaded runtime manifests carry a package SHA-256 and an orion-app://bundle/ identity; they are loaded as opaque-origin browser frames with the same reviewed, consent-based capabilities. External hosting instructions on this page apply only to the optional HTTPS format.
Design & accessibility
Use ORION's supplied theme to select a real light or dark palette. Do not invert the whole page or images. The starter supplies paired CSS variables, native color-scheme, visible focus and comfortable type. Keep your own product's identity; do not counterfeit the shell, consent dialogs or system warnings.
• Support narrow frames and a resizable desktop window. Avoid fixed page widths.
• Make all actions reachable with a keyboard and give controls visible labels.
• Aim for at least 4.5:1 contrast for normal text and 3:1 for large text/UI cues.
• Use semantic headings, native controls and polite status messages.
• Preserve entered work through recoverable errors. Do not reset a form on theme
changes. Make save status explicit, and confirm discarding substantial work.
• Honor prefers-reduced-motion. Caption video and provide text equivalents.
• Do not rely on color alone for status or use tiny hover-only controls.
• Test light and dark, 390px width, zoom, keyboard focus and unavailable services.
Native shell window controls belong to ORION. The isolated app should supply its own content toolbar, forms and navigation, without duplicate traffic lights.
Application artwork
Make one original icon with a clear subject, consistent lighting, strong contrast and generous margins. Avoid tiny text or a screenshot of the app. Keep an editable vector master, then export a square PNG at 256 or 512 pixels. Preview it at 20, 48 and 80 pixels on light and dark backgrounds. ORION applies the common rounded mask; do not bake in an outer drop shadow.
App Store → Developers → My apps → Listing → App artwork lets you choose, replace, remove and preview the PNG. The SDK includes icon.png in both starters. To embed your own artwork:
node bin/orion-app.mjs icon path/to/project path/to/artwork.png
node bin/orion-app.mjs check path/to/project
node bin/orion-app.mjs package path/to/project
The manifest carries the PNG data, so the image is part of the immutable reviewed release. ORION never fetches a developer image server when rendering Applications, Dock, search or window artwork. Only PNG is supported for external apps; native ORION artwork uses trusted vector assets. Uploaded packages support 3 MB total, including a 2 MB self-contained runtime. Submission metadata supports up to 1.8 MB including embedded PNG screenshots. The optional external-host metadata packager remains conservatively bounded at 58 KB. Apps with no artwork use a stable letter tile. Missing or undecodable artwork also falls back safely; it does not block launch. Artwork changes follow the same versioned submission and review process as other metadata.
Develop & deploy
Local preview
Use Node 20+. From this extracted kit, run npm run dev, then visit http://localhost:4173. No dependency install is required. It serves a synthetic ORION host on port 4173 and the Vanilla app on 4174, both bound to loopback. Change appearance and toggle organization sharing. Check standalone behavior at http://localhost:4174/examples/vanilla/index.html. Ctrl+C stops both servers. This is a local simulation, not the live App Store or an authentication service.
If a port is in use, stop the other process or edit both the server and the exact origins in dev/host.html and examples/vanilla/config.js. A mismatched origin is expected to receive no context.
Create a project
node bin/orion-app.mjs create my-app creates a new folder with the starter, compiled library and a local host. It refuses to overwrite an existing folder. In that folder run npm run dev and open http://localhost:4173. You do not need npm install. Edit the app, configure its host origin, then deploy the app files. Do not deploy the development host. Keep the SDK license beside copied code.
Production
• In config.js set development=false and the exact ORION origin you support.
• Replace the example manifest identity, publisher, name, description and URL.
• Serve the app and dist/library files with valid JavaScript MIME types on HTTPS.
• Configure your server CSP frame-ancestors https://www.orionos.app for the
actual host(s). Do not send X-Frame-Options: DENY or SAMEORIGIN on this integration route. Keep strict headers for unrelated pages as appropriate.
• Test a separate browser session, mobile width, keyboard navigation, no network,
loading failures and a non-installed organization. Serve useful errors.
• Send your manifest and public app URL to the ORION platform curator for review.
Third-party cookie restrictions apply in browser and desktop WebViews. Use your own deliberate sign-in design; no automatic ORION sign-in or session transfer is available. Do not promise an external browser flow can open from the frame: the v1 sandbox does not grant popup or top-navigation permissions.
Rebuild the package
Only source changes require npm install then npm run build. npm test runs against the compiled library. No private registry or credentials are needed.
For the recommended ORION-hosted format, see Upload without hosting. Uploaded runtime manifests carry a package SHA-256 and an orion-app://bundle/ identity; they are loaded as opaque-origin browser frames with the same reviewed, consent-based capabilities. External hosting instructions on this page apply only to the optional HTTPS format.
Manifest reference
Copy examples/vanilla/orion.manifest.json. All fields except icon are required.
| Field | Rules |
|---|---|
| sdkVersion | Integer 1 |
| id | Permanent reverse-domain style ID, up to 100 characters; lowercase letters, numbers, dots and hyphens; starts with a letter and includes a dot |
| name | Nonblank, at most 80 characters |
| summary | Nonblank, at most 240 characters |
| version | Three numeric components, optionally a lowercase prerelease suffix |
| publisher | Nonblank, at most 100 characters |
| launchUrl | HTTPS URL, at most 2,048 characters |
| icon | Optional embedded PNG data URI; square 128–512 pixels, at most 24 KB decoded. No remote URLs, SVG, animation or embedded EXIF. |
| capabilities | Zero to eight unique values: theme, organization.public, profile.basic, documents.read.selected, documents.create, clipboard.write, notifications.show, shell.open |
IDs beginning orion. or app-store. are reserved. Launch URLs cannot contain credentials, explicit non-default ports or fragments. Local names, numeric IP addresses and ORION's own domains/subdomains are rejected. ORION also checks that the launch origin differs from the actual host at launch, including custom hosts. Use a stable URL under your own controlled HTTPS domain. Updating its code is your responsibility and remains subject to the reviewed app's stated behavior.
node bin/orion-app.mjs validate examples/vanilla/orion.manifest.json
Example domains must be replaced before submission. Validation confirms format; it does not prove that a domain is yours, a URL is reachable or an app is safe.
For the recommended ORION-hosted format, see Upload without hosting. Uploaded runtime manifests carry a package SHA-256 and an orion-app://bundle/ identity; they are loaded as opaque-origin browser frames with the same reviewed, consent-based capabilities. External hosting instructions on this page apply only to the optional HTTPS format.
Native ORION platform contributions
The App SDK supports uploaded browser apps and independently hosted applications. Native React apps are reviewed contributions to the private ORION platform, not installable iframe packages. Downloading this kit does not grant platform repository access.
For an authorized native contribution, platform maintainers handle:
• Shell app definitions and dock/launcher registration, labels and category.
• Tenant-level app availability and OPE View/Edit policies.
• Window lifecycle, dirty-document save/discard behavior and command routing.
• Organization-aware server request context and API authorization.
• Tenant migrations, replay-safe provisioning and schema compatibility.
• Browser/Desktop/mobile behavior, accessibility and release verification.
Server routes must resolve the active organization from validated request context. Never use an HLN-only service client for a tenant request. UI hiding is not authorization. Keep operations scoped and audit privileged changes. Use the platform's existing primitives after checking the current repository; there are no downloadable privileged shell handles in this SDK.
Request an authorized contribution workflow from the ORION maintainers if your feature needs native window integration or a new private-data capability.
For the recommended ORION-hosted format, see Upload without hosting. Uploaded runtime manifests carry a package SHA-256 and an orion-app://bundle/ identity; they are loaded as opaque-origin browser frames with the same reviewed, consent-based capabilities. External hosting instructions on this page apply only to the optional HTTPS format.
Security & troubleshooting
Trust boundaries
Pin the exact host origin and verify the sender window. Never use * for context messages. Do not treat context, organization slug, nonce or app installation as an authentication credential. Never request ORION cookies, service keys, tokens or private connection files. If your app has users, authenticate them against your own service and enforce authorization on your server for every operation.
Do not import server-only ORION helpers into a distributed app. In particular, the platform's database clients, API middleware, OPE functions and UCI session implementation are not public SDK APIs. Public data still deserves accurate privacy documentation; avoid logging context unnecessarily.
Common failures
| Symptom | Check |
|---|---|
| No context | Exact https origin (including www), parent/source check, initialized listener, requested capability |
| Blank iframe | App URL reachable, valid TLS, CSP frame-ancestors, X-Frame-Options and JavaScript MIME types |
| App not listed | Curator approval, correct organization, personal installation and App Store access |
| Cannot open | Personal installation, current catalog approval and no organization block |
| Theme never changes | Capability includes theme; use updated host for live updates; do not recreate your app on each message |
| Local preview cannot start | Node 20+, ports 4173/4174 free, run from extracted package |
| Browser storage blocked | Do not depend on third-party cookies; keep a standalone/recovery path |
| Invalid manifest | Run validator and inspect docs/manifest.md; localhost is for local test host only |
Keep developer tools logs free of credentials. Report reproducible defects with SDK version, ORION version, browser/Desktop version and a synthetic sample. Never attach an organization's private database or member records.
Private-data actions require one-use approval, current OPE and a reviewed scope. Review limits, reporting, suspension and retention in Actions and approval.
For the recommended ORION-hosted format, see Upload without hosting. Uploaded runtime manifests carry a package SHA-256 and an orion-app://bundle/ identity; they are loaded as opaque-origin browser frames with the same reviewed, consent-based capabilities. External hosting instructions on this page apply only to the optional HTTPS format.
Upload an app without hosting
ORION can store, review and distribute your runnable web app. You do not need a public HTTPS server or DNS verification for this format. Existing HTTPS-hosted apps remain supported as a separate option.
Prepare a package
• In the SDK folder, run npm install. The local build tools are pinned in the lockfile. Build tools run on your computer, never on ORION's application server.
• Create your app with node bin/orion-app.mjs create ../my-app. Edit its manifest, submission metadata and application code.
• Add written supportText and privacyText to listing in orion.submission.json, or supply existing HTTPS policy pages. Run node bin/orion-app.mjs screenshot ../my-app screenshot.png to embed a screenshot and edit its caption. Screenshots can also be embedded PNG data URLs; the ORION editor also accepts screenshot uploads. Use synthetic data only.
• Run node bin/orion-app.mjs bundle ../my-app. This creates com.example.my-app-1.0.0.orion-app containing the metadata and runnable HTML. The packager bundles local JavaScript, CSS and supported images/fonts, and calculates the runtime SHA-256.
• In App Store → Developers → My apps, choose Upload app package, inspect it and Save draft. ORION uploads and screens the exact runnable build. Inspect any blocking findings or review flags under App build.
• Run the isolated preview, then open Review & submit and submit. Track the queue and review messages in Activity.
For a React/Vite project, build it locally first, then run node bin/orion-app.mjs bundle ../my-app dist/index.html. Use relative assets (base: './' in Vite) and keep the build output inside the project. node_modules may supply local build dependencies, but never include environment files, service keys, passwords or production data. No dependency install scripts are sent to ORION.
Supported runtime
Uploaded apps are self-contained browser applications, up to 2 MB of runnable HTML and 3 MB for the complete package. They do not run arbitrary server processes, native binaries or installation scripts. Remote resources, network requests, nested frames, forms, popups, workers, parent DOM access and persistent origin storage are restricted by the host. Use declared ORION capabilities and the existing member-approved broker for supported document and identity actions. In-memory state lasts until the window closes; save through an approved document action when persistence is needed.
The host supplies window.__ORION_PACKAGE_HOST__, its public origin only. The starter config uses it to connect through the SDK. Keep the SDK's exact-origin, source-window and nonce checks. No session or database credential is supplied.
The build identifier in a submitted manifest uses runtime: {kind: 'bundle', sha256: '...'} and an orion-app://bundle/... identity. That identifier is not a web address; ORION loads only the matching, approved stored bytes. Do not invent or edit a digest. Rebuild whenever code changes.
Review and decisions
Automatic screening detects obvious secrets, unsupported embedded runtimes and suspicious patterns. A passing report is not a malware guarantee. Warnings require reviewer inspection; blocking findings require a replacement build. Review uses synthetic profile and Work Suite responses, with no access to real documents, clipboard, accounts or production writes.
A curator claims the submission, opens that exact build, tests the documented flows and records the functionality, privacy, security and accessibility checks. They may request changes, deny with actionable reasons, or approve and publish. Developers and reviewers can exchange messages in Activity. Requested changes create a new frozen revision; rejected updates never replace the existing live release.
Approval publishes into ORION's existing curated Store channel. Members with Store access install for their own account and open the app from Applications. Updated capabilities or a change between external hosting and ORION hosting requires renewed member consent. Organization blocks, platform suspension, reports and revocation continue to apply.
Submission, review and updates
ORION App Store submissions are self-service for members who have App Store access. Your drafts belong to your signed-in account in the current organization. Only an ORION platform curator can publish a global release. An organization administrator cannot publish globally merely by administering their own organization.
Uploaded apps — recommended
Follow Upload an app without hosting. Use bundle to submit the executable browser app itself. ORION screens, privately stores and previews the exact build, then distributes the approved bytes. Public hosting and DNS verification are not required. Written support/privacy information and uploaded PNG screenshots are accepted.
Externally hosted apps — optional
The following package workflow is for apps that already have their own HTTPS host.
Prepare a release
• Generate a project with node bin/orion-app.mjs create my-app. For React, use node bin/orion-app.mjs create my-react-app --react.
• In the generated folder run npm run dev. The React project first needs npm install. Open the synthetic ORION test host at http://localhost:4173.
• Edit orion.manifest.json, orion.submission.json and config.js. Replace every example address and screenshot. Use an exact trusted production ORION origin and turn off the development flag before hosting.
• Host the app on your own independent public HTTPS origin. Allow framing by the exact ORION origins you support. Test the hosted release, keyboard access, compact windows, appearance, errors, denied approvals and dirty-window closure. Use synthetic data.
• From the SDK folder run node bin/orion-app.mjs check path/to/my-app. This reads the actual manifest, metadata and entry point. It validates metadata, not the safety or functionality of hosted code.
• Run node bin/orion-app.mjs package path/to/my-app. This creates a deterministic .orion-submission.json review packet. Existing output files are never overwritten. An optional final argument chooses a new output file.
The packet contains listing and testing metadata. It does not upload or execute source code or create a hosted app. No ORION token, API key or developer credential is needed in the CLI.
Save and submit in ORION
For uploaded apps, use App build to inspect screening and run the isolated preview. Hosting verification below applies only to external apps.
Open App Store → Developers → My apps. Choose New app for the guided editor, or Import SDK packet. Use Store listing, Capabilities and Testing & release to complete the record.
Save draft to reserve your stable reverse-domain ID. This does not publish the app. Another account cannot claim that ID or edit your draft. Use Activity to exchange review messages and see actionable denial or change reasons. IDs of established platform-maintained apps are reserved to the platform.
In Capabilities, copy the verification address and contents. Publish the plain-text file on the app's launch origin under /.well-known/orion-apps/<your-app-id>.txt, then choose Verify launch origin. Verification requires an unredirected HTTPS 200 response and expires after seven days. It proves hosting control, not legal publisher identity, code immutability or security approval. Private/local network addresses are refused.
Open Submit for review. Resolve preflight issues and choose Submit release. The snapshot is frozen. Follow decisions in Activity. Withdraw a pending release without affecting the current published version. If changes are requested, choose Create a revision, edit the new private draft, save and submit again.
What reviewers receive
Provide a useful description, written support/privacy information or existing policy pages, one to five uploaded PNG or HTTPS screenshots with descriptions, a reason for every capability, release notes and reproducible testing instructions. Describe data destinations, persistence, deletion, network use and limitations. Do not include member records, passwords, tokens, private connection files or test-account credentials. Support/privacy information is public; testing instructions stay private to the author and curators.
Platform curators use Review Apps to claim a release, inspect metadata and capability changes, test it, record the checklist and decision notes, request changes, reject or explicitly Approve & publish. First-party or self review must be acknowledged and recorded as such. Metadata preflight and domain verification are not a human security audit. Curators also inspect reports in App safety.
Publish an update
From your published submission choose Create next version. Use a stable numeric version higher than the live release: 1.10.0 follows 1.9.0. Complete fresh release notes, save, verify the launch origin if necessary and submit. The previous release continues working during review. Rejection, requested changes and withdrawal do not remove it.
Normal publication preserves personal installations. Changing the launch origin or adding capabilities pauses those installations until each member chooses Review update and accepts the release. The app remains in Installed during this pause. Old pending SDK approvals are invalidated whenever the manifest changes. Every subsequent private action still requires member approval and current OPE permissions.
Suspension, retirement and organization blocks are separate App safety actions. Suspension preserves installations but disables launch and broker access. Retirement removes installations. No SDK request can restore access or bypass these decisions. Removing your personal install does not delete data held on the developer's independent service; provide a deletion/export process where applicable.
Hosted code responsibility
Remote hosting can change after review. Keep approved version URLs stable, deploy intentionally, maintain support/privacy information and submit new releases for material changes. ORION isolates the frame and brokers capabilities; it cannot certify every future byte served by an independent host. Never ask a member to paste a session token into your app or treat public display context as identity evidence.
Include your icon
Choose the PNG in Listing → App artwork or embed it with orion-app icon <project-folder> <artwork.png>. Preview Applications, Dock and menu sizes before submitting. Use the design guide for export limits. The image is frozen with the submitted manifest and is visible to reviewers. It does not grant capabilities or change installation permissions.
Work Suite interoperability
SDK 1.2 supports ORION’s owned-file picker and new private Write, Grid and Present files through brokered actions. See Actions and approval. File listing stays in ORION; only the selected file is shared after approval. Existing files cannot be overwritten or deleted through this SDK. Deliberate portable-file export/import also remains supported.
Portable .orion.json files use {version:1, kind, title, body}. The examples/files folder contains synthetic Write, Grid and Present files accepted by the current portable format. Do not add owner IDs, permissions, revisions or database IDs.
• Write: kind:'write', body {text:string}, up to 200,000 characters.
• Grid: kind:'grid', body {cells:string[][]}, a rectangular grid of 1–200 rows
and 1–26 columns, at most 2,000 characters per cell.
• Present: kind:'present', body {slides:[{id,title,body,notes}]}; 1–100 slides,
unique IDs up to 80 characters, titles up to 200, body/notes up to 8,000 each.
• Title: nonblank and at most 160 characters. The import file limit is 2 MB.
Read files only after the user selects them. Validate length, envelope and content before use. Render content as text, never unsanitized HTML. Do not execute spreadsheet cells, scripts or embedded markup. Presenter notes may be private; remove them when producing a student or public copy. Exporting/importing a file does not transfer ORION sharing grants or ownership.
Write also accepts text/Markdown and Grid accepts CSV. PowerPoint .pptx is not the same as ORION Present's portable format; do not claim direct compatibility.