Release, URLs, and Access Control
Once an application is written, three things decide whether it can go live safely: how it's released, where users come in, and who can access what.
The release flow
Submit a version from the Builder's Publish tab.
- Record a version number and a changelog
- Behavior depends on permission:
- With
builder.publish→ publishes directly - Without → creates a publish request for review
- With
Requests can be approved, rejected (with a reason), or cancelled by the requester. This makes "who can push code to production" a controllable responsibility rather than something every developer holds.
What release freezes
Publishing does more than ship code — it freezes an authorization snapshot:
- Reference declarations (which tables, which columns, which operations)
- Scope declarations
Which means changing reference settings during development does not affect the live version. A new release is required. That is deliberate: it prevents anyone from quietly widening permissions in development and having it take effect against production data immediately.
Blocking pre-release checks
The platform detects configuration gaps at release time and blocks:
| Check | Why it blocks |
|---|---|
| External service not authorized | Code calls an external service whose domain hasn't been added to the allowlist |
| Fewer actions than before | This version dropped actions — possibly by accident; explicit confirmation required |
Both are classic "blows up in front of users after go-live" failures, hence catching them before release.
Note: the pre-release check only verifies that a service is authorized (domain allowlist). The platform neither stores nor validates external service credentials — they live in App Secrets, and each action reads them out and assembles its own
Authorizationheader. If an external API returns401after go-live, the application's own credentials are at fault; that is outside what the pre-release check can catch.
URLs and identifiers
Every application carries two identifiers with different purposes:
| Random identifier | Readable name | |
|---|---|---|
| Chosen by | The system | You |
| Mutable | No | Yes, before release |
| Used for | Permanently stable internal identity | The public URL |
Readable name rules:
- 4–63 characters, lowercase alphanumerics and hyphens, not starting or ending with a hyphen
- Case-insensitive (
MyAppnormalizes tomyapp) - Reserved words are blocked (
admin,api,www,login, and others) - Globally unique across organizations; collisions are rejected
If your organization has chosen a workspace name, the public subdomain carries an organization prefix (of the form {workspace}-{app}). Always use the URL the system returns rather than deriving it from the organization name — existing applications are never renamed, so old and new conventions can coexist.
After release the URL is the user's entry point. Administrators copy it from the Dashboard and distribute it.
Lifecycle management
| Operation | Effect |
|---|---|
| Republish | Ships a new version; users get it on next load |
| Suspend | Holders of the URL can no longer sign in; settings and code are retained |
| Delete | Removes the application and its URL. Data Center data is not deleted |
Deleting an app without deleting data is deliberate — data belongs to the organization, not to an application. It's the same principle that makes custom tables organization-level.
Four layers of access control
What an application can touch is decided by four stacked layers. All four must pass.
Layer 1: who can see the application
Internal apps can be restricted to specific roles — only members holding those roles see it in the application list and can sign in.
To a user who lacks access, the application is indistinguishable from nonexistent: it isn't listed, opening the URL directly is refused, and the response matches "no such application" so its existence isn't leaked.
Layer 2: reference declarations (data scope)
An application must declare which ERP tables, columns, and operations it needs:
{
"table_name": "customers",
"columns": ["id", "name", "email", "custom_data"],
"permissions": ["read", "create", "update"]
}
Undeclared tables are unreachable. Declared tables with undeclared columns return nothing on read and silently drop them on write.
Permission values:
| Value | Allows |
|---|---|
read | Query |
create | Insert |
update | Update |
delete | Delete |
Practical advice: do not grant delete to ordinary operational applications. Model voiding as a status change and leave real deletion to administrators in a controlled environment. That preserves the audit trail and prevents accidents.
Core system tables (authentication, tenant management, permission settings, audit records) can never be referenced.
Layer 3: scope approval (capability scope)
References govern which data. Scope governs which capabilities.
An application declares the scopes it needs (a code scan backfills them at release), and an administrator approves them in the Builder's Scope tab.
High-risk scopes require an extra gate: expanding into db.write, erp.*, secret.read, http, knowledge.read, and similar requires the owner to enter their password on the spot. This defends against authorization being widened quietly — even a compromised administrator account cannot escalate without the password.
External and Self-Built applications require explicit administrator approval and do not use the simplified internal flow.
Every scope grant change is recorded — who, when, and which scope — and is queryable in the audit log.
Layer 4: user permissions (RBAC)
Even when the application is authorized, actual operations remain bound by the user's roles. Internal apps can read the triggering user's permission tags and decide what to show and allow.
Final server-side adjudication uses the triggering user's identity — a hidden front-end button is not a boundary.
The three access modes compared
| Internal | External | Self-Built | |
|---|---|---|---|
| Use case | Internal tooling | Customer / supplier applications | Third-party system integration |
| Authentication | Organization member accounts | The app's own user system | API key |
| Code location | AI GO Builder | AI GO Builder | Deployed by the third party |
| Data access | Internal Proxy | External Proxy | Open Proxy |
| References need publishing | No (immediate) | No (immediate) | Yes (published snapshot) |
Self-Built serves the case of "we don't want to write code inside AI GO, we just want the data". It has no Builder and no front end — only an API key and data access. See Chapter 11.
Auditing
All of the following are recorded:
- Application creation, release, suspension, deletion
- Reference declaration changes
- Scope grant changes (including who performed them)
- Every SDK call
Audit records are queryable under System & Operations → Audit Log with the system.audit_log permission.