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
12 changes: 8 additions & 4 deletions docs/static-export-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,14 @@ build is green; the bundle is not yet runtime-functional from a `localhost` orig
`http://tauri.localhost` (Tauri on Windows) origins, and the shell injecting the
token from Face-ID-gated secure storage.

- [ ] **C. `/content/*` embedded-chat proxy — localized**
`src/app/components/openframe-chat-runtime-provider.tsx` relies on the `rewrites()`
same-origin proxy (omitted under export). Switch to absolute gateway URLs + Bearer
+ CORS (the provider already has cross-origin/Bearer logic).
- [x] **C. `/content/*` embedded-chat proxy — localized** *(frontend side done
2026-07-17; gateway CORS for `/content/*` from the shell origins still item B)*
In the native shell, `help-center/endpoints.ts` (`CONTENT_ORIGIN`) and the chat
runtime provider absolutize every `/content` URL to the tenant gateway, and the
chat `EmbedAuthAdapter` sanctions that origin via the core lib's new
`allowedOrigins` field on `embedAuthedFetch`'s cross-origin guard
(openframe-frontend-core `embed-authed-fetch.ts`). Web builds keep the
relative same-origin base + `rewrites()`/reverse-proxy path unchanged.

- [ ] **D. Native-shell SPA fallback** so cold loads of non-prerendered paths resolve
to the app shell client-side: the help-center CMS routes (placeholder-only), and any
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"core:unlink": "yalc remove @flamingo-stack/openframe-frontend-core"
},
"dependencies": {
"@flamingo-stack/openframe-frontend-core": "^0.0.442",
"@flamingo-stack/openframe-frontend-core": "^0.0.446",
"@hookform/resolvers": "^5.2.2",
"@monaco-editor/react": "^4.7.0",
"@tanstack/react-query": "^5.90.16",
Expand Down
148 changes: 144 additions & 4 deletions schema.graphql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Auto-generated by scripts/fetch-schema.mjs via introspection
# Source: https://test-dev.openframe.build/api/graphql
# Generated: 2026-07-09T19:23:04.279Z
# Source: https://test-frontend.openframe.build/api/graphql
# Generated: 2026-07-15T10:27:33.577Z
#
# Do not edit manually. Re-run: npm run fetch-schema
directive @extends on OBJECT | INTERFACE
Expand Down Expand Up @@ -57,6 +57,7 @@ type AdminApprovalRequestContext implements NotificationContext {
approvalRequestId: ID!
dialogId: ID!
ticketId: ID
ticketNumber: Int
approvalType: ApprovalType!
toolCalls: [ApprovalToolCall!]!
resolution: ApprovalResolution
Expand Down Expand Up @@ -284,6 +285,15 @@ input CreateScriptInput {
tagIds: [ID!]
}

input CreateScriptScheduleInput {
name: String!
description: String
supportedPlatforms: [ScriptPlatform!]

"""Ids of existing Scripts to run, in run order."""
scriptIds: [ID!]
}

input CreateTimeEntryInput {
userId: ID!
ticketId: ID
Expand Down Expand Up @@ -1048,6 +1058,13 @@ type Mutation {
"""Update the current subscription (change packages, toggle PAYG)."""
updateSubscription(input: UpdateSubscriptionInput!): UpdateSubscriptionResult!

"""
Cancel a pending package downgrade, reverting to the current (higher) tier. Drops the deferred
PENDING_ACTIVATION option and its queued Stripe schedule phase so the scheduled reduction never takes
effect. Errors if there is no pending downgrade.
"""
cancelPendingDowngrade: UpdateSubscriptionResult!

"""Detach all payment methods. Returns the count of detached methods."""
detachPaymentMethods: Int!

Expand Down Expand Up @@ -1076,6 +1093,37 @@ type Mutation {
markAllNotificationsAsRead: Int!
deleteNotification(notificationId: ID!): Boolean!
deleteAllReadNotifications: Int!

"""
Create a new schedule. Returns the created schedule with its server-assigned id.
"""
createScriptSchedule(input: CreateScriptScheduleInput!): ScriptSchedule!

"""
Full replacement (PUT semantics) of an existing schedule: every writable field on the input overwrites the stored value, including nulls which clear optional fields. The target schedule id travels inside the input.
"""
updateScriptSchedule(input: UpdateScriptScheduleInput!): ScriptSchedule!

"""
Soft-delete a schedule (sets status to DELETED). Returns the id of the deleted schedule; idempotent on already-deleted schedules. Throws if the id is not found in the tenant.
"""
deleteScriptSchedule(id: ID!): ID!

"""
Archive a schedule (sets status to ARCHIVED). Idempotent. Returns the updated schedule. Throws if not found or soft-deleted.
"""
archiveScriptSchedule(id: ID!): ScriptSchedule!

"""
Restore an archived schedule back to ACTIVE. Idempotent. Returns the updated schedule. Throws if not found or soft-deleted.
"""
unarchiveScriptSchedule(id: ID!): ScriptSchedule!

"""
Replace the full set of devices assigned to a schedule (PUT semantics — backs "Edit Devices").
machineIds are Machine global ids. Returns the updated schedule. Throws if the schedule is not found or soft-deleted.
"""
setScriptScheduleDevices(scheduleId: ID!, machineIds: [ID!]!): ScriptSchedule!
createFolder(name: String!, parentId: ID): KnowledgeBaseItem!
renameFolder(id: ID!, name: String!): KnowledgeBaseItem!
createArticle(input: CreateArticleInput!): KnowledgeBaseItem!
Expand Down Expand Up @@ -1468,6 +1516,20 @@ type Query {
notifications(filter: NotificationFilterInput, search: String, first: Int, after: String, last: Int, before: String, sort: SortInput): NotificationConnection!
hasUnreadNotifications: Boolean!
unreadCountsByCategory: [UnreadCategoryCount!]!

"""
Get a single schedule by id within the current tenant. Throws (not null) if the id is absent, soft-deleted, or in another tenant.
"""
scriptSchedule(id: ID!): ScriptSchedule!

"""
Cursor-paginated list of schedules within the current tenant (Relay Connection Spec).
Default order is newest-first by _id. Optional filter / search / sort.
Sortable fields: _id (default), name, createdAt, updatedAt. Search is a
case-insensitive substring match on name.
"""
scriptSchedules(filter: ScriptScheduleFilterInput, search: String, sort: SortInput, first: Int, after: String, last: Int, before: String): ScriptScheduleConnection!
scriptScheduleFilters(filter: ScriptScheduleFilterInput): ScriptScheduleFilters!
knowledgeBaseItems(filter: KnowledgeBaseFilterInput, search: String, first: Int, after: String): KnowledgeBaseItemConnection!
knowledgeBaseItem(id: ID!): KnowledgeBaseItem
knowledgeBaseTags(folderId: ID, archived: Boolean): [Tag!]!
Expand Down Expand Up @@ -1544,7 +1606,7 @@ type Query {
""" YYYY-MM-DD format"""
toolType: String!

""" Tool type (meshcentral, tactical-rmm, etc.)"""
""" Tool type (meshcentral, fleet-mdm, etc.)"""
eventType: String!

""" Event type (login, logout, script, etc.)"""
Expand Down Expand Up @@ -1739,6 +1801,71 @@ enum ScriptPlatform {
MACOS
}

type ScriptSchedule implements Node {
id: ID!
name: String!
description: String
supportedPlatforms: [ScriptPlatform!]

"""
The scripts this schedule runs, in run order (resolved from the stored script ids).
"""
scripts: [Script!]!

"""
Machines assigned to this schedule (resolved from the assignment collection via the machine loader).
"""
assignedDevices: [Machine!]!

"""Number of machines assigned to this schedule (the DEVICES column)."""
deviceCount: Int!

"""
Lifecycle status: ACTIVE | ARCHIVED | DELETED. DELETED is a soft-delete and is hidden from default queries.
"""
status: ScriptStatus!
statusChangedAt: Instant
createdAt: Instant
updatedAt: Instant

"""
The creating user (resolved from the internal createdBy id via the user DataLoader).
"""
author: User
}

type ScriptScheduleConnection {
edges: [ScriptScheduleEdge!]!
pageInfo: PageInfo!

"""
Total number of schedules matching the current filter/search for the tenant, independent of pagination.
"""
filteredCount: Int!
}

type ScriptScheduleEdge {
node: ScriptSchedule!
cursor: String!
}

"""
Filter for the scriptSchedules(...) query. All fields optional — null/empty means
no constraint. The statuses field hides DELETED when null/empty; when supplied it
is used verbatim.
"""
input ScriptScheduleFilterInput {
statuses: [ScriptStatus!]
supportedPlatforms: [ScriptPlatform!]
authorIds: [ID!]
}

type ScriptScheduleFilters {
platforms: [ScriptFilterOption!]!
authors: [ScriptFilterOption!]!
filteredCount: Int!
}

enum ScriptShell {
POWERSHELL
CMD
Expand Down Expand Up @@ -2025,6 +2152,8 @@ type TicketAssignedContext implements NotificationContext {
ticketNumber: Int
assigneeUserId: ID!
assignedByUserId: ID
assigneeName: String
assignedByName: String
}

type TicketStatusChangedContext implements NotificationContext {
Expand Down Expand Up @@ -2128,7 +2257,6 @@ type ToolList {

enum ToolType {
MESHCENTRAL
TACTICAL_RMM
FLEET_MDM
OPENFRAME_RMM
}
Expand Down Expand Up @@ -2197,6 +2325,18 @@ input UpdateScriptInput {
tagIds: [ID!]
}

"""
Full-replacement (PUT) payload for an existing schedule. Optional fields accept
null to clear the stored value; name cannot be null.
"""
input UpdateScriptScheduleInput {
id: ID!
name: String!
description: String
supportedPlatforms: [ScriptPlatform!]
scriptIds: [ID!]
}

input UpdateSubscriptionInput {
packageUpdates: [PackageUpdateInput!]
discountCode: String
Expand Down
Loading
Loading