@k2b/cloud 0.49.0 → 0.50.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k2b/cloud",
3
- "version": "0.49.0",
3
+ "version": "0.50.0",
4
4
  "description": "Application platform library for independently deployed Hono and SolidJS services behind a dynamic gateway.",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "repository": {
@@ -131,7 +131,7 @@
131
131
  "@tailwindcss/typography": "0.5.20",
132
132
  "@k2b/nessi": "0.18.0",
133
133
  "@k2b/ssr": "0.20.2",
134
- "@k2b/ui": "0.38.1",
134
+ "@k2b/ui": "0.39.0",
135
135
  "@k2b/stdlib": "0.30.0",
136
136
  "@k2b/sync": "7.0.1",
137
137
  "@nats-io/jetstream": "3.4.0",
@@ -163,7 +163,7 @@
163
163
  "hash-wasm": "4.12.0",
164
164
  "@types/sanitize-html": "2.16.1",
165
165
  "@types/web-push": "3.6.4",
166
- "@k2b/editor": "0.2.0"
166
+ "@k2b/editor": "0.3.0"
167
167
  },
168
168
  "devDependencies": {
169
169
  "@babel/core": "8.0.6",
@@ -2,6 +2,7 @@ import { managerEligibility } from "../_internal/app-access-manager-sql";
2
2
  import { sql } from "../runtime/clients";
3
3
  import type { RequestAuthority } from "../server/middleware/auth";
4
4
  import { AppAccessManagementError, canRepairAppAccess } from "./app-access-management";
5
+ import type { LastRejectedStart } from "./app-keys";
5
6
 
6
7
  export type AppAdminFacts = {
7
8
  access: { people: number; groups: number; serviceAccounts: number; managers: number; configured: boolean } | null;
@@ -14,12 +15,14 @@ export type AppAdminFacts = {
14
15
  accountStatus: "active" | "disabled" | null;
15
16
  };
16
17
  tokens: { active: number; total: number };
18
+ /** Core's last refusal of a start with a verified proof; cleared by the next successful start. */
19
+ lastRejectedStart: Omit<LastRejectedStart, "keyId"> | null;
17
20
  events: { hears: number; sends: number | null; failedDeliveries: number; waitingDeliveries: number };
18
21
  notifications: number | null;
19
22
  firstKnownAt: string | null;
20
23
  };
21
24
 
22
- /** Core-owned administration summary: at most 500 input IDs and four batched SQL reads. */
25
+ /** Core-owned administration summary: at most 500 input IDs and five batched SQL reads. */
23
26
  export const appAdminFacts = async (authority: RequestAuthority, appIds: readonly string[]): Promise<Map<string, AppAdminFacts>> => {
24
27
  if (!canRepairAppAccess(authority)) throw new AppAccessManagementError("FORBIDDEN", "Cloud administration authority is required.");
25
28
  if (appIds.length > 500) throw new AppAccessManagementError("TOO_MANY_APPS", "At most 500 application IDs may be read at once.", 400);
@@ -31,6 +34,7 @@ export const appAdminFacts = async (authority: RequestAuthority, appIds: readonl
31
34
  access: null,
32
35
  keys: { active: 0, expired: 0, revoked: 0, lastUsedAt: null, firstCreatedAt: null, accountStatus: null },
33
36
  tokens: { active: 0, total: 0 },
37
+ lastRejectedStart: null,
34
38
  events: { hears: 0, sends: 0, failedDeliveries: 0, waitingDeliveries: 0 },
35
39
  notifications: 0,
36
40
  firstKnownAt: null,
@@ -39,7 +43,7 @@ export const appAdminFacts = async (authority: RequestAuthority, appIds: readonl
39
43
  );
40
44
  if (!ids.length) return facts;
41
45
 
42
- const [access, credentials, events, notifications] = await Promise.all([
46
+ const [access, credentials, events, notifications, rejections] = await Promise.all([
43
47
  sql<
44
48
  {
45
49
  app_id: string;
@@ -125,6 +129,9 @@ export const appAdminFacts = async (authority: RequestAuthority, appIds: readonl
125
129
  SELECT app_id, count(*)::int AS count FROM notifications.definitions
126
130
  WHERE app_id IN ${sql(ids)} AND active = true GROUP BY app_id
127
131
  `,
132
+ sql<{ app_id: string; rejected_at: Date; reason: LastRejectedStart["reason"] }[]>`
133
+ SELECT app_id, rejected_at, reason FROM auth.app_start_rejections WHERE app_id IN ${sql(ids)}
134
+ `,
128
135
  ]);
129
136
 
130
137
  for (const row of access) {
@@ -156,5 +163,6 @@ export const appAdminFacts = async (authority: RequestAuthority, appIds: readonl
156
163
  facts.get(row.app_id)!.events = { hears: row.hears, sends: row.sends, failedDeliveries: row.failed, waitingDeliveries: row.waiting };
157
164
  }
158
165
  for (const row of notifications) facts.get(row.app_id)!.notifications = row.count;
166
+ for (const row of rejections) facts.get(row.app_id)!.lastRejectedStart = { at: row.rejected_at.toISOString(), reason: row.reason };
159
167
  return facts;
160
168
  };
@@ -152,7 +152,7 @@ export const bindDocuments = <Saved, Context>(
152
152
  // A request cancelled while the callback ran must not publish a write.
153
153
  options.signal?.throwIfAborted();
154
154
  const beforeEditState = Y.encodeStateVector(doc);
155
- const finishHistory = options.actionId ? prepareStructuralHistory(ytext, changes) : undefined;
155
+ const finishHistory = options.actionId ? prepareStructuralHistory(ytext, changes) : prepareIngressHistory(ytext);
156
156
  if (prepared) {
157
157
  // Application-prepared transactions preserve exact item identities and
158
158
  // may be replayed after a partial publication/persistence failure.
@@ -168,7 +168,7 @@ export const bindDocuments = <Saved, Context>(
168
168
  const actor = options.actor;
169
169
  const updateBytes = Y.encodeStateAsUpdate(doc, beforeEditState);
170
170
  const receipt = options.actionId ? { actionId: options.actionId, update: updateBytes } : undefined;
171
- const history: SharedTextStructuralHistory = finishHistory?.() ?? { patches: [], tables: [], ingressBarrier: true };
171
+ const history: SharedTextStructuralHistory = finishHistory();
172
172
  if (history && options.inverseOf) {
173
173
  history.inverseOf = options.inverseOf;
174
174
  history.retained = options.retained?.() ?? false;