> For the complete documentation index, see [llms.txt](https://docs.layeronecloud.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.layeronecloud.com/platform/web-hosting/management.md).

# Management jobs, files, databases and applications

Once active, each customer change is a separate immutable WebHostingManagementJob.

## 6.4 Management jobs <a href="#id-64-management-jobs" id="id-64-management-jobs"></a>

Once active, each customer change is a separate immutable `WebHostingManagementJob`. Domain/subdomain, reviewed Apache policy, account-scoped PHP Selector, Python/Node application, MySQL/PostgreSQL, hosted-mail, backup and tenant-file metadata controls use **closed schemas**. The portal sends **no executable, raw httpd configuration, host path, password, environment value or customer file content** in these jobs.

Transport: the portal submits only a persisted 32-character idempotency request ID, the typed action name, the immutable hosting account ID, and the operation-specific resource object to `POST /v2/actions`. It does **not** construct or send a node job ID or a portal generation. The node assigns the `act-*` identity, owns execution sequencing, and returns queued/running/terminal state with a bounded timestamped event timeline, which the portal persists and renders. **Portal generations are private desired-state dedupe bookkeeping and are not presented as node authority.**

Immediate post-commit Celery dispatch polls itself through every node in-flight state, while `webhosting.dispatch_management_jobs` (`WEBHOSTING_MANAGEMENT_DISPATCH_INTERVAL_SECONDS`=15) recovers a task lost to a worker or broker restart. Healthy actions are observed every two seconds with **one leased step per job**, so duplicate deliveries cannot create extra polling chains; transport failures back off; resource successors wake as soon as their predecessor finishes. Two no-progress deadlines (`WEBHOSTING_MANAGEMENT_SUBMITTED_NO_PROGRESS_TIMEOUT_SECONDS` and `..._RUNNING_...`, both 120 s) fail an action whose state, event stream and node-reported update timestamp have not advanced — **identical HTTP poll responses do not reset them.**

**The node must report the matching resource identity and generation before the portal marks desired state active.** Credential requests for a database still converging remain **queued behind** that structural job rather than being rejected by the customer interface.

Failed database and mail-domain rows expose an owned **retry**: it locks the existing resource, proves its newest intent is the matching terminal failure, advances **one** generation, and queues a fresh typed action under the same immutable resource ID. An in-flight or newer intent suppresses retry.

While a non-file workspace has pending/submitted/running work, the control center refreshes that workspace through the shared bounded polling contract (750 ms), rendering pending→running transitions in place and using a **non-secret digest of active request-ID membership** to reload resource rows when membership changes — including when one completed job is replaced and the active count stays the same. Polling stops when every visible job is terminal.

Instance and tool navigation render stored portal state **without waiting for a node account read**. Once the workspace appears, a one-shot ownership-checked CSRF-protected POST observes the account and replaces only the account notice and progress panel. Missing-account repairs reuse the same durable idempotent jobs. Automatic progress refreshes do not start another account observation; late responses are discarded after navigation; observation failures leave the workspace usable. A successful account read is reused for `WEBHOSTING_ACCOUNT_ACCESS_CACHE_SECONDS` (30) across workspace navigation while local ownership, service state, node binding and desired limits stay unchanged.

`webhosting.sync_nodes`, `webhosting.renew_domain_certificates` (`WEBHOSTING_CERTIFICATE_RENEWAL_INTERVAL_SECONDS`=3600), `webhosting.dispatch_customer_dns_jobs` (`WEBHOSTING_CUSTOMER_DNS_DISPATCH_INTERVAL_SECONDS`=15) and `webhosting.meter_hourly_usage` must keep running: **placement, management reconciliation, certificate renewal, retries and hourly metering are durable asynchronous workflows, so restarting only the web process leaves them queued.**

Operator surfaces show portal/node identity, resource counts, provisioning state and durable jobs; suspend an active service; restore a suspended one **only while its billing account is active**; or cancel a not-yet-active reservation with typed confirmation. Failed jobs retain and display the node's bounded failure stage, exception type, error code, job identity and operator-safe summary. **A pending removal remains visibly `Deleting`; node polling cannot reset it to the contradictory `Applying` state.** Raw command/provider output, paths, request bodies and credentials stay outside the portal record.

## 6.5 Files <a href="#id-65-files" id="id-65-files"></a>

**Customer file bytes use a separate bounded file-transfer protocol, never a management-job payload or a portal database row.** Uploads declare their size and SHA-256 digest before streaming; downloads use a one-time node receipt; the small text editor accepts only bounded UTF-8 tenant files. Signed download and edit URLs are excluded from activity, analytics, audit-path storage and session recording, and served with `no-store`/`no-referrer`.

The **File Manager** is a live browser rooted at the customer's complete hosting home. There is **no domain/document-root selector**: `Home` is path `""` and every breadcrumb stays relative to the immutable account identity sent to the node. It renders the node's current bounded directory page **including dotfiles**, shows the resolved user and group owner for every listed inode, and offers a local filter, explicit pagination, create-folder, copy, rename, move through a folder picker, recoverable move-to-trash, upload, download and bounded UTF-8 edit.

* A **move preserves the existing name** and reuses the node's typed `rename_path` operation with a different parent; it never overwrites a destination or falls back to copy-and-delete.
* **Symlinks are displayed but never followed as directories.**
* Tenant-owned sockets, FIFOs, devices and unsupported inode types are shown as `other`: they cannot be opened, downloaded or edited, but their descriptor-relative no-follow Rename and Trash actions remain available.
* Entries the node cannot safely represent are omitted and reported by `skipped_count`.
* The node's internal home-root `.layerone-trash` namespace is hidden and cannot be named or addressed by a customer request; the same ordinary name remains usable inside nested customer directories.

Interactive file requests use the node's ordinary typed `POST /v1/actions` and `GET /v1/actions/{request_id}` contract **directly** — they create no `WebHostingFileOperation` or `WebHostingManagementJob` rows. An already-terminal result returns in the same HTTP exchange; a bounded `202` carries a signed service-bound status URL the browser polls every 250 ms. The page shows an in-pane spinner and bounded inline failure, discards stale navigation responses, and refreshes the current directory after a mutation without reloading the workspace. Browser back/forward restores live directory state, and an ambiguous mutation retry reuses its original idempotency token. Upload and download move bytes through the same action's `/content` endpoint. **No file contents, directory listings or navigation clicks are persisted in the portal database or logs.** This is not a generic command surface: every request is a closed typed operation resolved below the node-owned tenant home. Copy, archive creation/extraction, resumable upload and permanent recursive purge are **not** exposed by this v1 contract.

**Guarded file editing.** File Manager and the standalone fallback page share a small self-hosted CodeMirror editor, loaded only when editing. Syntax highlighting, line numbers, indentation, search, undo/redo, cursor position, keyboard save and an unsaved-change guard are client-side; **there is no code execution, external CDN, draft persistence or content logging**, the native textarea remains usable if the enhancement cannot load, and both editor surfaces are **session-replay masked**. Pinned dependencies, licenses, provenance and a reproducible bundle build live under `scripts/code_editor/` and `static/vendor/codemirror/`.

The editor can edit a tenant-owned `.htaccess` inside a `public_html` tree. It never exposes a generated virtual host, `httpd.conf`, another tenant's tree or any root-owned Apache file.

The portal preserves UTF-8 content and surrounding whitespace, including empty files, and sends the opened file's SHA-256 as an optional typed `upload_file_content.expected_sha256` **precondition**. The tenant worker checks it at publication, preserves ordinary permissions, and atomically replaces the regular file. Stale, removed or non-regular targets fail without being recreated. An advisory inode lock serializes overlapping node editor workers — **this is not a filesystem-wide compare-and-swap** against unrelated writers that ignore advisory locks.

**Submission or accepted bytes are not save confirmation.** The portal and editor require the matching account/action and a terminal `written` result with the exact submitted byte count. Queued saves return an owned signed poll URL; a browser retry reuses its intent token (bound to account, path, opened digest and new content digest) and does not upload already-received bytes again. **An unavailable status observation is `unconfirmed`, not proof of failure or absence of changes** — the editor retains the draft and the same retry receipt, and only confirmed success advances the saved baseline.

The live File Manager starts at the tenant's complete home, so customers navigate either document-root layout without typing or controlling a host path.

## 6.6 Databases, credentials and applications <a href="#id-66-databases-credentials-and-applications" id="id-66-databases-credentials-and-applications"></a>

**New database actions send only the customer's logical 1–32 character label.** The node derives the physical name from its root-owned account mapping as `<resolved-username>_<full-label>` — the portal no longer truncates labels. Immutable pre-upgrade actions that already contain a physical `name` remain valid for **exact replay**, and successful node results persist the observed physical name for later credential verification. Databases are **account** resources and are deliberately **not** part of a domain removal.

**One-time sealed credential delivery.** Database and mailbox passwords use a separate credential lane — never `WebHostingManagementJob.request_payload`, results, task logs or audit metadata. On **Generate credential** / **Rotate credential** the portal locks the owned active resource, increments one credential generation, creates a **request-specific RSA-3072 key pair**, and Fernet-encrypts the private key. The authenticated HTTPS node API receives only the **public key**, immutable IDs, operation, generation and a **fourteen-minute mutation lease** — above the node's ten-minute pre-mutation safety floor and below its fifteen-minute protocol maximum, for clock-skew tolerance. The node returns the same sealed **RSA-OAEP-SHA256** offer until the portal has transactionally stored Fernet ciphertext and explicitly acknowledged the exact request/envelope hashes, so lost consume or acknowledgement responses replay safely; terminal node expiry fails and **purges that generation** so a new rotation can be requested rather than retried forever.

The customer then uses the POST-only **Reveal once** action. Ownership is checked again under a database lock; the recoverable encrypted credential is **deleted and marked revealed before the response is rendered**. That response has **no base layout, scripts, analytics, session recording or third-party assets** and sends `no-store`/CSP/`no-referrer`/`nosniff`. Its fixed `/client/web-hosting-credentials/` path is excluded from request activity, analytics, audit-path storage and recordings. A second request cannot recover the password. The separate fifteen-minute reveal window starts **only after the node acknowledges the durable portal ciphertext**; an unrevealed credential is purged when that window expires (`webhosting.dispatch_credential_deliveries`, `webhosting.expire_credential_deliveries`).

**A node must advertise both the qualified structural operations and its separately qualified matching credential rotation** before MySQL, PostgreSQL or mail controls become available. Do not mark PostgreSQL available until the node enforces and reads back storage quotas, and do not mark mail available until DNS/TLS/SMTP/IMAP, quota, relay, cross-tenant and reputation staging passes.

**Applications and releases.** Typed Python/WSGI, Django and Node release management with bounded USTAR artifact upload, immutable candidate/active/rollback generations, separately sealed environment-secret delivery, and one-time sanitized log tails. **Django schema migration remains closed until a backup-bound step-up flow exists.** The portal commits an exact artifact ID, expiry, size, digest, dependency digest, release and generation **before** node I/O; a lost create/content response is recovered by exact replay or GET, **changed bytes cannot adopt the intent**, and a terminal or pruned artifact requires a fresh release generation. Runtime logs remain masked and one-time, with an explicitly focusable scroll region.

**Scheduled tasks** are structured hourly/daily/weekly/monthly PHP, Python and Node jobs bound to an owned domain or active application. **Customers never submit cron text, executable paths, shell syntax, environment values or output content.**

**Backups.** Persisted backup resources, plan metadata, historical management jobs, admin inspection and rolling-deployment reconciliation are retained, but **no customer backup creation, restore, retention deletion or in-place account replacement is exposed.** Reintroducing that surface requires a separately authorized design and a proven restore/rollback workflow. Retained plan metadata (`webhosting.0018`): LET Beta 1 backup / 7-day retention / 1 per 24 h; Starter 2 / 7 days / 1 per 24 h; Developer 5 / 14 days / 1 per 6 h; Business 10 / 30 days / 1 per hour.

**Stack contract.** Customer traffic uses CloudLinux-provided Apache with `mod_hostinglimits`, `mod_lsapi` and Passenger. PHP Selector is a first-class plan and node capability. **PostgreSQL management is a separate typed capability and must not be described as governed by MySQL Governor.** The portal never exposes a root command endpoint or a raw Apache configuration editor.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.layeronecloud.com/platform/web-hosting/management.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
