@graph8/sdk 0.13.1 → 0.14.0

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/dist/react.d.mts CHANGED
@@ -1915,6 +1915,272 @@ declare const createObjectsClient: (apiKey: string, apiUrl?: string) => {
1915
1915
  history(objectSlug: string, recordId: string, limit?: number): Promise<CustomObjectHistory>;
1916
1916
  };
1917
1917
 
1918
+ /**
1919
+ * Hosted app platform — deployments, domains, secrets, source and logs (M9 J14).
1920
+ *
1921
+ * WHAT WAS MISSING. `apps.ts` covered creating an app and reading its installs,
1922
+ * usage and limit. Everything that actually SHIPS one -- binding a source,
1923
+ * queueing a deployment, promoting it, attaching a hostname, reading why a build
1924
+ * failed -- had no client at all. That is why the build portal is read-only: not
1925
+ * because the routes are absent, but because nothing typed reached them.
1926
+ *
1927
+ * EVERY RESPONSE ON THIS SURFACE IS WRAPPED as `{data, pagination}`, and
1928
+ * `pagination` is always null here -- none of these routes paginate. The helpers
1929
+ * below unwrap `data` so callers work with the record, except where the list IS
1930
+ * the answer.
1931
+ *
1932
+ * DELIBERATELY ABSENT, and each for a reason:
1933
+ *
1934
+ * * `POST /apps/{id}/deployments/{id}/status` -- authenticated with the build
1935
+ * CONTROLLER credential, not a builder's API key. An SDK method for it would
1936
+ * imply a customer can move their own deployment through the state machine.
1937
+ * * `GET /app-platform/tls-authorize` -- Caddy's on-demand-TLS ask hook. Public,
1938
+ * unauthenticated, returns a bare 200 or 404 with no body. It is edge
1939
+ * plumbing, not a customer API.
1940
+ */
1941
+ /** The six frozen values. Not widened to `string`: a client that switches on the
1942
+ * status should get a compile error when a new state is added. */
1943
+ type DeploymentStatus = "queued" | "building" | "promoting" | "deployed" | "failed" | "rolled_back";
1944
+ type DomainVerificationStatus = "pending" | "verified" | "failed" | "revoked";
1945
+ type SourceProvider = "github" | "gitlab" | "bitbucket";
1946
+ type SchemaVersionStatus = "draft" | "published" | "deprecated";
1947
+ interface Deployment {
1948
+ deployment_id: string;
1949
+ app_id: string;
1950
+ /** One of `DeploymentStatus`. Typed as the union, but the server sends a plain
1951
+ * string -- treat an unrecognised value as forward compatibility, not an error. */
1952
+ status: DeploymentStatus;
1953
+ source_ref: string | null;
1954
+ image_digest: string | null;
1955
+ schema_version_id: string | null;
1956
+ /** Sanitized at the WRITE. One line. The detail is in `logs()`. */
1957
+ last_error_sanitized: string | null;
1958
+ created_at: string | null;
1959
+ deployed_at: string | null;
1960
+ build_started_at: string | null;
1961
+ build_finished_at: string | null;
1962
+ /** Measured `building` -> `promoting`, NOT to `deployed`: `deployed` is reached
1963
+ * after traffic is taken, so measuring to it would count the promotion too. */
1964
+ build_seconds: number | null;
1965
+ }
1966
+ interface CreateDeploymentParams {
1967
+ /** A COMMIT-ish, never a branch name. A branch moves, so a deployment recorded
1968
+ * against one cannot answer "what is running right now" a week later. The
1969
+ * server enforces length only -- this convention is the caller's to keep. */
1970
+ source_ref: string;
1971
+ /** Pins the custom-object schema this build expects, so a rollback restores the
1972
+ * matching schema and not merely the matching image. */
1973
+ schema_version_id?: string;
1974
+ }
1975
+ interface AppDomain {
1976
+ domain_id: string;
1977
+ app_id: string;
1978
+ /** The canonical normalized form -- lowercased, trailing dot stripped, IDNA
1979
+ * encoded. NOT what you submitted. */
1980
+ hostname: string;
1981
+ status: DomainVerificationStatus;
1982
+ verification_token: string | null;
1983
+ created_at: string | null;
1984
+ verified_at: string | null;
1985
+ }
1986
+ interface DomainVerificationInstructions {
1987
+ domain: AppDomain;
1988
+ record_type: "TXT";
1989
+ record_name: string;
1990
+ record_value: string;
1991
+ }
1992
+ interface AppSecretMetadata {
1993
+ secret_key: string;
1994
+ /** A POINTER into your secret manager, never the secret. graph8 has no column
1995
+ * for a value and cannot grow one. */
1996
+ provider_ref: string | null;
1997
+ created_at: string | null;
1998
+ rotated_at: string | null;
1999
+ }
2000
+ interface AppSourceParams {
2001
+ repo_url: string;
2002
+ provider: SourceProvider;
2003
+ default_branch?: string;
2004
+ credential_ref?: string;
2005
+ }
2006
+ interface SchemaVersion {
2007
+ schema_version_id: string;
2008
+ app_id: string;
2009
+ version: number;
2010
+ digest: string;
2011
+ status: SchemaVersionStatus;
2012
+ manifest: Record<string, unknown>;
2013
+ created_at: string | null;
2014
+ published_at: string | null;
2015
+ deprecated_at: string | null;
2016
+ }
2017
+ interface ContainerLog {
2018
+ pod: string;
2019
+ container: string;
2020
+ /** `init` steps run to completion before the pod's containers start. A build is
2021
+ * four init steps (fetch, scan-source, build, scan-image) then one container
2022
+ * (push), so this is how you tell which step you are looking at. */
2023
+ kind: "init" | "container";
2024
+ text: string;
2025
+ /** The tail hit the per-container byte cap. Earlier output exists and was not
2026
+ * returned. */
2027
+ truncated: boolean;
2028
+ }
2029
+ interface AppLogs {
2030
+ app_id: string;
2031
+ /** Set for build logs; null for the running app's logs. */
2032
+ deployment_id: string | null;
2033
+ namespace: string;
2034
+ tail_lines: number;
2035
+ /**
2036
+ * Always true, and it means only that graph8's credential patterns ran.
2037
+ * It is NOT a claim the output is safe to publish: these are your own build and
2038
+ * application logs, and an application can print a secret in a shape no pattern
2039
+ * matches.
2040
+ */
2041
+ redacted: boolean;
2042
+ containers: ContainerLog[];
2043
+ }
2044
+ declare const createAppPlatformClient: (apiKey: string, apiUrl?: string) => {
2045
+ /**
2046
+ * Bind the repository an app builds from.
2047
+ *
2048
+ * `repo_url` must be fetchable -- `https://`, `ssh://` or `git@`, with no
2049
+ * whitespace. A `file://` or bare path is refused with 422, because a build
2050
+ * that can read the builder's filesystem is a build that can read ours.
2051
+ *
2052
+ * `credential_ref` is a POINTER into your secret manager, not a token.
2053
+ */
2054
+ setSource(appId: string, params: AppSourceParams): Promise<Record<string, unknown>>;
2055
+ /** Unbind the source. Returns the full app with every source field null. */
2056
+ clearSource(appId: string): Promise<Record<string, unknown>>;
2057
+ /** Every deployment for this app, newest first. Never 404s for an app with none. */
2058
+ listDeployments(appId: string): Promise<{
2059
+ data: Deployment[];
2060
+ }>;
2061
+ /**
2062
+ * Queue a deployment. Returns `201` with `status: "queued"` -- nothing builds
2063
+ * as a side effect of this call; the build controller picks it up.
2064
+ *
2065
+ * NOT idempotent: two identical calls create two deployments.
2066
+ */
2067
+ deploy(appId: string, params: CreateDeploymentParams): Promise<Deployment>;
2068
+ /** Fetch one deployment. The polling endpoint for a build loop. */
2069
+ getDeployment(appId: string, deploymentId: string): Promise<Deployment>;
2070
+ /**
2071
+ * The deployment currently serving traffic, or `null`.
2072
+ *
2073
+ * `null` is a real answer with a 200, not a 404: "this app has never shipped"
2074
+ * is information, while a 404 would read as "no such app".
2075
+ */
2076
+ activeDeployment(appId: string): Promise<Deployment | null>;
2077
+ /**
2078
+ * Promote a built deployment to serve traffic. Anything it displaces moves to
2079
+ * `rolled_back` in the same transaction, so there is never a moment with two
2080
+ * live deployments.
2081
+ *
2082
+ * `409` when the state machine forbids it -- a deployment cannot become
2083
+ * `deployed` without having been built, and a `failed` one cannot be revived.
2084
+ * A retry is a new deployment, not a resurrection.
2085
+ */
2086
+ promote(appId: string, deploymentId: string, imageDigest: string): Promise<Deployment>;
2087
+ /** Roll back a deployment that is currently serving. Only a `deployed` one may be. */
2088
+ rollback(appId: string, deploymentId: string): Promise<Deployment>;
2089
+ /**
2090
+ * Why a build failed. Returns every step of the build pod in the order
2091
+ * Kubernetes runs them; a step that has not started yet is omitted rather
2092
+ * than returned empty.
2093
+ *
2094
+ * An empty `containers` list is not an error -- build pods are reaped an hour
2095
+ * after they finish, so logs for an older deployment are genuinely gone.
2096
+ * `last_error_sanitized` on the deployment is what survives.
2097
+ *
2098
+ * `503` means graph8 could not reach the cluster, which is deliberately
2099
+ * different from an empty `200`: one means we could not look, the other means
2100
+ * your build produced no output.
2101
+ */
2102
+ deploymentLogs(appId: string, deploymentId: string, tailLines?: number): Promise<AppLogs>;
2103
+ /**
2104
+ * What the running app is printing. The app's own pods only -- the per-app
2105
+ * egress proxy shares the namespace and is deliberately excluded.
2106
+ *
2107
+ * Empty until a deployment reaches `deployed`.
2108
+ */
2109
+ logs(appId: string, tailLines?: number): Promise<AppLogs>;
2110
+ /** Every hostname claimed for this app, whatever its verification state. */
2111
+ listDomains(appId: string): Promise<{
2112
+ data: AppDomain[];
2113
+ }>;
2114
+ /**
2115
+ * Claim a hostname and get the TXT record that proves you own it.
2116
+ *
2117
+ * Returns `201`, and the domain is NESTED at `data.domain` -- this is the one
2118
+ * route on the surface whose payload is not the record itself. Hostnames are
2119
+ * globally unique, so a host another app holds is refused.
2120
+ */
2121
+ claimDomain(appId: string, hostname: string): Promise<DomainVerificationInstructions>;
2122
+ /**
2123
+ * Check DNS for the TXT record and advance the domain to `verified`.
2124
+ *
2125
+ * Idempotent: verifying an already-verified domain re-checks and stays
2126
+ * verified, so it is safe to re-run after a DNS change. Send no body -- the
2127
+ * record in DNS is the payload.
2128
+ */
2129
+ verifyDomain(appId: string, hostname: string): Promise<AppDomain>;
2130
+ /**
2131
+ * Release a claimed hostname.
2132
+ *
2133
+ * A HARD delete. Hostnames are globally unique, so a row left behind in any
2134
+ * status keeps the host burned for every other builder. Releasing one you
2135
+ * already released is a `404`, because after the first call the claim
2136
+ * genuinely does not exist.
2137
+ *
2138
+ * Returns the NORMALIZED hostname, which may differ from what you passed.
2139
+ */
2140
+ releaseDomain(appId: string, hostname: string): Promise<{
2141
+ hostname: string;
2142
+ released: boolean;
2143
+ }>;
2144
+ /**
2145
+ * Which secrets this app declares, and when each was last rotated.
2146
+ *
2147
+ * NEVER returns a value. graph8 stores a POINTER into your secret manager and
2148
+ * has no column for the secret itself.
2149
+ */
2150
+ listSecrets(appId: string): Promise<{
2151
+ data: AppSecretMetadata[];
2152
+ }>;
2153
+ /**
2154
+ * Declare a secret, or rotate the pointer to it.
2155
+ *
2156
+ * `providerRef` is a REFERENCE, and the server rejects anything that looks
2157
+ * like a credential -- a value starting `bearer `, `sk-`, `ghp_`, `xox` and
2158
+ * friends is a 422. That refusal is the feature: it catches the mistake of
2159
+ * pasting the secret where its address belongs.
2160
+ */
2161
+ putSecret(appId: string, secretKey: string, providerRef?: string): Promise<AppSecretMetadata>;
2162
+ /** Undeclare a secret. A key the app never declared is a 404, so a typo is
2163
+ * never reported as a successful removal. */
2164
+ deleteSecret(appId: string, secretKey: string): Promise<{
2165
+ secret_key: string;
2166
+ removed: boolean;
2167
+ }>;
2168
+ /**
2169
+ * Publish a custom-object schema version. Returns `201`.
2170
+ *
2171
+ * Takes only the `objects` list, not a whole `graph8.app.yaml`: the rest of
2172
+ * that file is app metadata the control plane already holds, and accepting it
2173
+ * here would create a second place for it to disagree.
2174
+ */
2175
+ publishSchemaVersion(appId: string, objects: unknown[]): Promise<{
2176
+ version: SchemaVersion;
2177
+ }>;
2178
+ /** Every schema version this app has published. Empty array, never 404. */
2179
+ listSchemaVersions(appId: string): Promise<{
2180
+ data: SchemaVersion[];
2181
+ }>;
2182
+ };
2183
+
1918
2184
  /**
1919
2185
  * App lifecycle. `draft` serves no traffic; `published` is live; `suspended` is a
1920
2186
  * platform action and cannot be set through this client; `archived` is retired.
@@ -3499,6 +3765,7 @@ declare const useG8: () => {
3499
3765
  _tasks: ReturnType<typeof createTasksClient> | null;
3500
3766
  _fields: ReturnType<typeof createFieldsClient> | null;
3501
3767
  _apps: ReturnType<typeof createAppsClient> | null;
3768
+ _appPlatform: ReturnType<typeof createAppPlatformClient> | null;
3502
3769
  _objects: ReturnType<typeof createObjectsClient> | null;
3503
3770
  _deals: ReturnType<typeof createDealsClient> | null;
3504
3771
  _inbox: ReturnType<typeof createInboxClient> | null;
@@ -3772,6 +4039,43 @@ declare const useG8: () => {
3772
4039
  usage(appId: string, period?: string): Promise<AppUsageSummary>;
3773
4040
  getLimit(appId: string): Promise<AppLimit | null>;
3774
4041
  };
4042
+ get appPlatform(): {
4043
+ setSource(appId: string, params: AppSourceParams): Promise<Record<string, unknown>>;
4044
+ clearSource(appId: string): Promise<Record<string, unknown>>;
4045
+ listDeployments(appId: string): Promise<{
4046
+ data: Deployment[];
4047
+ }>;
4048
+ deploy(appId: string, params: CreateDeploymentParams): Promise<Deployment>;
4049
+ getDeployment(appId: string, deploymentId: string): Promise<Deployment>;
4050
+ activeDeployment(appId: string): Promise<Deployment | null>;
4051
+ promote(appId: string, deploymentId: string, imageDigest: string): Promise<Deployment>;
4052
+ rollback(appId: string, deploymentId: string): Promise<Deployment>;
4053
+ deploymentLogs(appId: string, deploymentId: string, tailLines?: number): Promise<AppLogs>;
4054
+ logs(appId: string, tailLines?: number): Promise<AppLogs>;
4055
+ listDomains(appId: string): Promise<{
4056
+ data: AppDomain[];
4057
+ }>;
4058
+ claimDomain(appId: string, hostname: string): Promise<DomainVerificationInstructions>;
4059
+ verifyDomain(appId: string, hostname: string): Promise<AppDomain>;
4060
+ releaseDomain(appId: string, hostname: string): Promise<{
4061
+ hostname: string;
4062
+ released: boolean;
4063
+ }>;
4064
+ listSecrets(appId: string): Promise<{
4065
+ data: AppSecretMetadata[];
4066
+ }>;
4067
+ putSecret(appId: string, secretKey: string, providerRef?: string): Promise<AppSecretMetadata>;
4068
+ deleteSecret(appId: string, secretKey: string): Promise<{
4069
+ secret_key: string;
4070
+ removed: boolean;
4071
+ }>;
4072
+ publishSchemaVersion(appId: string, objects: unknown[]): Promise<{
4073
+ version: SchemaVersion;
4074
+ }>;
4075
+ listSchemaVersions(appId: string): Promise<{
4076
+ data: SchemaVersion[];
4077
+ }>;
4078
+ };
3775
4079
  get objects(): {
3776
4080
  list(): Promise<{
3777
4081
  data: CustomObject[];
package/dist/react.d.ts CHANGED
@@ -1915,6 +1915,272 @@ declare const createObjectsClient: (apiKey: string, apiUrl?: string) => {
1915
1915
  history(objectSlug: string, recordId: string, limit?: number): Promise<CustomObjectHistory>;
1916
1916
  };
1917
1917
 
1918
+ /**
1919
+ * Hosted app platform — deployments, domains, secrets, source and logs (M9 J14).
1920
+ *
1921
+ * WHAT WAS MISSING. `apps.ts` covered creating an app and reading its installs,
1922
+ * usage and limit. Everything that actually SHIPS one -- binding a source,
1923
+ * queueing a deployment, promoting it, attaching a hostname, reading why a build
1924
+ * failed -- had no client at all. That is why the build portal is read-only: not
1925
+ * because the routes are absent, but because nothing typed reached them.
1926
+ *
1927
+ * EVERY RESPONSE ON THIS SURFACE IS WRAPPED as `{data, pagination}`, and
1928
+ * `pagination` is always null here -- none of these routes paginate. The helpers
1929
+ * below unwrap `data` so callers work with the record, except where the list IS
1930
+ * the answer.
1931
+ *
1932
+ * DELIBERATELY ABSENT, and each for a reason:
1933
+ *
1934
+ * * `POST /apps/{id}/deployments/{id}/status` -- authenticated with the build
1935
+ * CONTROLLER credential, not a builder's API key. An SDK method for it would
1936
+ * imply a customer can move their own deployment through the state machine.
1937
+ * * `GET /app-platform/tls-authorize` -- Caddy's on-demand-TLS ask hook. Public,
1938
+ * unauthenticated, returns a bare 200 or 404 with no body. It is edge
1939
+ * plumbing, not a customer API.
1940
+ */
1941
+ /** The six frozen values. Not widened to `string`: a client that switches on the
1942
+ * status should get a compile error when a new state is added. */
1943
+ type DeploymentStatus = "queued" | "building" | "promoting" | "deployed" | "failed" | "rolled_back";
1944
+ type DomainVerificationStatus = "pending" | "verified" | "failed" | "revoked";
1945
+ type SourceProvider = "github" | "gitlab" | "bitbucket";
1946
+ type SchemaVersionStatus = "draft" | "published" | "deprecated";
1947
+ interface Deployment {
1948
+ deployment_id: string;
1949
+ app_id: string;
1950
+ /** One of `DeploymentStatus`. Typed as the union, but the server sends a plain
1951
+ * string -- treat an unrecognised value as forward compatibility, not an error. */
1952
+ status: DeploymentStatus;
1953
+ source_ref: string | null;
1954
+ image_digest: string | null;
1955
+ schema_version_id: string | null;
1956
+ /** Sanitized at the WRITE. One line. The detail is in `logs()`. */
1957
+ last_error_sanitized: string | null;
1958
+ created_at: string | null;
1959
+ deployed_at: string | null;
1960
+ build_started_at: string | null;
1961
+ build_finished_at: string | null;
1962
+ /** Measured `building` -> `promoting`, NOT to `deployed`: `deployed` is reached
1963
+ * after traffic is taken, so measuring to it would count the promotion too. */
1964
+ build_seconds: number | null;
1965
+ }
1966
+ interface CreateDeploymentParams {
1967
+ /** A COMMIT-ish, never a branch name. A branch moves, so a deployment recorded
1968
+ * against one cannot answer "what is running right now" a week later. The
1969
+ * server enforces length only -- this convention is the caller's to keep. */
1970
+ source_ref: string;
1971
+ /** Pins the custom-object schema this build expects, so a rollback restores the
1972
+ * matching schema and not merely the matching image. */
1973
+ schema_version_id?: string;
1974
+ }
1975
+ interface AppDomain {
1976
+ domain_id: string;
1977
+ app_id: string;
1978
+ /** The canonical normalized form -- lowercased, trailing dot stripped, IDNA
1979
+ * encoded. NOT what you submitted. */
1980
+ hostname: string;
1981
+ status: DomainVerificationStatus;
1982
+ verification_token: string | null;
1983
+ created_at: string | null;
1984
+ verified_at: string | null;
1985
+ }
1986
+ interface DomainVerificationInstructions {
1987
+ domain: AppDomain;
1988
+ record_type: "TXT";
1989
+ record_name: string;
1990
+ record_value: string;
1991
+ }
1992
+ interface AppSecretMetadata {
1993
+ secret_key: string;
1994
+ /** A POINTER into your secret manager, never the secret. graph8 has no column
1995
+ * for a value and cannot grow one. */
1996
+ provider_ref: string | null;
1997
+ created_at: string | null;
1998
+ rotated_at: string | null;
1999
+ }
2000
+ interface AppSourceParams {
2001
+ repo_url: string;
2002
+ provider: SourceProvider;
2003
+ default_branch?: string;
2004
+ credential_ref?: string;
2005
+ }
2006
+ interface SchemaVersion {
2007
+ schema_version_id: string;
2008
+ app_id: string;
2009
+ version: number;
2010
+ digest: string;
2011
+ status: SchemaVersionStatus;
2012
+ manifest: Record<string, unknown>;
2013
+ created_at: string | null;
2014
+ published_at: string | null;
2015
+ deprecated_at: string | null;
2016
+ }
2017
+ interface ContainerLog {
2018
+ pod: string;
2019
+ container: string;
2020
+ /** `init` steps run to completion before the pod's containers start. A build is
2021
+ * four init steps (fetch, scan-source, build, scan-image) then one container
2022
+ * (push), so this is how you tell which step you are looking at. */
2023
+ kind: "init" | "container";
2024
+ text: string;
2025
+ /** The tail hit the per-container byte cap. Earlier output exists and was not
2026
+ * returned. */
2027
+ truncated: boolean;
2028
+ }
2029
+ interface AppLogs {
2030
+ app_id: string;
2031
+ /** Set for build logs; null for the running app's logs. */
2032
+ deployment_id: string | null;
2033
+ namespace: string;
2034
+ tail_lines: number;
2035
+ /**
2036
+ * Always true, and it means only that graph8's credential patterns ran.
2037
+ * It is NOT a claim the output is safe to publish: these are your own build and
2038
+ * application logs, and an application can print a secret in a shape no pattern
2039
+ * matches.
2040
+ */
2041
+ redacted: boolean;
2042
+ containers: ContainerLog[];
2043
+ }
2044
+ declare const createAppPlatformClient: (apiKey: string, apiUrl?: string) => {
2045
+ /**
2046
+ * Bind the repository an app builds from.
2047
+ *
2048
+ * `repo_url` must be fetchable -- `https://`, `ssh://` or `git@`, with no
2049
+ * whitespace. A `file://` or bare path is refused with 422, because a build
2050
+ * that can read the builder's filesystem is a build that can read ours.
2051
+ *
2052
+ * `credential_ref` is a POINTER into your secret manager, not a token.
2053
+ */
2054
+ setSource(appId: string, params: AppSourceParams): Promise<Record<string, unknown>>;
2055
+ /** Unbind the source. Returns the full app with every source field null. */
2056
+ clearSource(appId: string): Promise<Record<string, unknown>>;
2057
+ /** Every deployment for this app, newest first. Never 404s for an app with none. */
2058
+ listDeployments(appId: string): Promise<{
2059
+ data: Deployment[];
2060
+ }>;
2061
+ /**
2062
+ * Queue a deployment. Returns `201` with `status: "queued"` -- nothing builds
2063
+ * as a side effect of this call; the build controller picks it up.
2064
+ *
2065
+ * NOT idempotent: two identical calls create two deployments.
2066
+ */
2067
+ deploy(appId: string, params: CreateDeploymentParams): Promise<Deployment>;
2068
+ /** Fetch one deployment. The polling endpoint for a build loop. */
2069
+ getDeployment(appId: string, deploymentId: string): Promise<Deployment>;
2070
+ /**
2071
+ * The deployment currently serving traffic, or `null`.
2072
+ *
2073
+ * `null` is a real answer with a 200, not a 404: "this app has never shipped"
2074
+ * is information, while a 404 would read as "no such app".
2075
+ */
2076
+ activeDeployment(appId: string): Promise<Deployment | null>;
2077
+ /**
2078
+ * Promote a built deployment to serve traffic. Anything it displaces moves to
2079
+ * `rolled_back` in the same transaction, so there is never a moment with two
2080
+ * live deployments.
2081
+ *
2082
+ * `409` when the state machine forbids it -- a deployment cannot become
2083
+ * `deployed` without having been built, and a `failed` one cannot be revived.
2084
+ * A retry is a new deployment, not a resurrection.
2085
+ */
2086
+ promote(appId: string, deploymentId: string, imageDigest: string): Promise<Deployment>;
2087
+ /** Roll back a deployment that is currently serving. Only a `deployed` one may be. */
2088
+ rollback(appId: string, deploymentId: string): Promise<Deployment>;
2089
+ /**
2090
+ * Why a build failed. Returns every step of the build pod in the order
2091
+ * Kubernetes runs them; a step that has not started yet is omitted rather
2092
+ * than returned empty.
2093
+ *
2094
+ * An empty `containers` list is not an error -- build pods are reaped an hour
2095
+ * after they finish, so logs for an older deployment are genuinely gone.
2096
+ * `last_error_sanitized` on the deployment is what survives.
2097
+ *
2098
+ * `503` means graph8 could not reach the cluster, which is deliberately
2099
+ * different from an empty `200`: one means we could not look, the other means
2100
+ * your build produced no output.
2101
+ */
2102
+ deploymentLogs(appId: string, deploymentId: string, tailLines?: number): Promise<AppLogs>;
2103
+ /**
2104
+ * What the running app is printing. The app's own pods only -- the per-app
2105
+ * egress proxy shares the namespace and is deliberately excluded.
2106
+ *
2107
+ * Empty until a deployment reaches `deployed`.
2108
+ */
2109
+ logs(appId: string, tailLines?: number): Promise<AppLogs>;
2110
+ /** Every hostname claimed for this app, whatever its verification state. */
2111
+ listDomains(appId: string): Promise<{
2112
+ data: AppDomain[];
2113
+ }>;
2114
+ /**
2115
+ * Claim a hostname and get the TXT record that proves you own it.
2116
+ *
2117
+ * Returns `201`, and the domain is NESTED at `data.domain` -- this is the one
2118
+ * route on the surface whose payload is not the record itself. Hostnames are
2119
+ * globally unique, so a host another app holds is refused.
2120
+ */
2121
+ claimDomain(appId: string, hostname: string): Promise<DomainVerificationInstructions>;
2122
+ /**
2123
+ * Check DNS for the TXT record and advance the domain to `verified`.
2124
+ *
2125
+ * Idempotent: verifying an already-verified domain re-checks and stays
2126
+ * verified, so it is safe to re-run after a DNS change. Send no body -- the
2127
+ * record in DNS is the payload.
2128
+ */
2129
+ verifyDomain(appId: string, hostname: string): Promise<AppDomain>;
2130
+ /**
2131
+ * Release a claimed hostname.
2132
+ *
2133
+ * A HARD delete. Hostnames are globally unique, so a row left behind in any
2134
+ * status keeps the host burned for every other builder. Releasing one you
2135
+ * already released is a `404`, because after the first call the claim
2136
+ * genuinely does not exist.
2137
+ *
2138
+ * Returns the NORMALIZED hostname, which may differ from what you passed.
2139
+ */
2140
+ releaseDomain(appId: string, hostname: string): Promise<{
2141
+ hostname: string;
2142
+ released: boolean;
2143
+ }>;
2144
+ /**
2145
+ * Which secrets this app declares, and when each was last rotated.
2146
+ *
2147
+ * NEVER returns a value. graph8 stores a POINTER into your secret manager and
2148
+ * has no column for the secret itself.
2149
+ */
2150
+ listSecrets(appId: string): Promise<{
2151
+ data: AppSecretMetadata[];
2152
+ }>;
2153
+ /**
2154
+ * Declare a secret, or rotate the pointer to it.
2155
+ *
2156
+ * `providerRef` is a REFERENCE, and the server rejects anything that looks
2157
+ * like a credential -- a value starting `bearer `, `sk-`, `ghp_`, `xox` and
2158
+ * friends is a 422. That refusal is the feature: it catches the mistake of
2159
+ * pasting the secret where its address belongs.
2160
+ */
2161
+ putSecret(appId: string, secretKey: string, providerRef?: string): Promise<AppSecretMetadata>;
2162
+ /** Undeclare a secret. A key the app never declared is a 404, so a typo is
2163
+ * never reported as a successful removal. */
2164
+ deleteSecret(appId: string, secretKey: string): Promise<{
2165
+ secret_key: string;
2166
+ removed: boolean;
2167
+ }>;
2168
+ /**
2169
+ * Publish a custom-object schema version. Returns `201`.
2170
+ *
2171
+ * Takes only the `objects` list, not a whole `graph8.app.yaml`: the rest of
2172
+ * that file is app metadata the control plane already holds, and accepting it
2173
+ * here would create a second place for it to disagree.
2174
+ */
2175
+ publishSchemaVersion(appId: string, objects: unknown[]): Promise<{
2176
+ version: SchemaVersion;
2177
+ }>;
2178
+ /** Every schema version this app has published. Empty array, never 404. */
2179
+ listSchemaVersions(appId: string): Promise<{
2180
+ data: SchemaVersion[];
2181
+ }>;
2182
+ };
2183
+
1918
2184
  /**
1919
2185
  * App lifecycle. `draft` serves no traffic; `published` is live; `suspended` is a
1920
2186
  * platform action and cannot be set through this client; `archived` is retired.
@@ -3499,6 +3765,7 @@ declare const useG8: () => {
3499
3765
  _tasks: ReturnType<typeof createTasksClient> | null;
3500
3766
  _fields: ReturnType<typeof createFieldsClient> | null;
3501
3767
  _apps: ReturnType<typeof createAppsClient> | null;
3768
+ _appPlatform: ReturnType<typeof createAppPlatformClient> | null;
3502
3769
  _objects: ReturnType<typeof createObjectsClient> | null;
3503
3770
  _deals: ReturnType<typeof createDealsClient> | null;
3504
3771
  _inbox: ReturnType<typeof createInboxClient> | null;
@@ -3772,6 +4039,43 @@ declare const useG8: () => {
3772
4039
  usage(appId: string, period?: string): Promise<AppUsageSummary>;
3773
4040
  getLimit(appId: string): Promise<AppLimit | null>;
3774
4041
  };
4042
+ get appPlatform(): {
4043
+ setSource(appId: string, params: AppSourceParams): Promise<Record<string, unknown>>;
4044
+ clearSource(appId: string): Promise<Record<string, unknown>>;
4045
+ listDeployments(appId: string): Promise<{
4046
+ data: Deployment[];
4047
+ }>;
4048
+ deploy(appId: string, params: CreateDeploymentParams): Promise<Deployment>;
4049
+ getDeployment(appId: string, deploymentId: string): Promise<Deployment>;
4050
+ activeDeployment(appId: string): Promise<Deployment | null>;
4051
+ promote(appId: string, deploymentId: string, imageDigest: string): Promise<Deployment>;
4052
+ rollback(appId: string, deploymentId: string): Promise<Deployment>;
4053
+ deploymentLogs(appId: string, deploymentId: string, tailLines?: number): Promise<AppLogs>;
4054
+ logs(appId: string, tailLines?: number): Promise<AppLogs>;
4055
+ listDomains(appId: string): Promise<{
4056
+ data: AppDomain[];
4057
+ }>;
4058
+ claimDomain(appId: string, hostname: string): Promise<DomainVerificationInstructions>;
4059
+ verifyDomain(appId: string, hostname: string): Promise<AppDomain>;
4060
+ releaseDomain(appId: string, hostname: string): Promise<{
4061
+ hostname: string;
4062
+ released: boolean;
4063
+ }>;
4064
+ listSecrets(appId: string): Promise<{
4065
+ data: AppSecretMetadata[];
4066
+ }>;
4067
+ putSecret(appId: string, secretKey: string, providerRef?: string): Promise<AppSecretMetadata>;
4068
+ deleteSecret(appId: string, secretKey: string): Promise<{
4069
+ secret_key: string;
4070
+ removed: boolean;
4071
+ }>;
4072
+ publishSchemaVersion(appId: string, objects: unknown[]): Promise<{
4073
+ version: SchemaVersion;
4074
+ }>;
4075
+ listSchemaVersions(appId: string): Promise<{
4076
+ data: SchemaVersion[];
4077
+ }>;
4078
+ };
3775
4079
  get objects(): {
3776
4080
  list(): Promise<{
3777
4081
  data: CustomObject[];