@unisonlabs/sixminute-admin 0.1.1183-next → 0.1.1185-next

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.
@@ -21,7 +21,7 @@ import { homedir } from "node:os";
21
21
  import { fileURLToPath } from "node:url";
22
22
 
23
23
  // tools/admin/src/build-info.ts
24
- var BUILT = { version: "0.1.1183-next", commit: "1ef7d5cae5e04dc99660239f6ff1b537c9fb4c37", surface: "6002dfcedab0aa31" };
24
+ var BUILT = { version: "0.1.1185-next", commit: "c9217149ea9d39117eeed671cb624b48d802ad69", surface: "60ffe6d6d98eb32b" };
25
25
 
26
26
  // tools/admin/src/run.ts
27
27
  import { rmSync as rmSync3 } from "node:fs";
@@ -4894,7 +4894,8 @@ var RoleSchema = exports_external.enum(["timekeeper", "billing", "admin"]);
4894
4894
  var TenantPolicySchema = exports_external.object({
4895
4895
  excluded_bundles: exports_external.array(exports_external.string().min(1)).default([]),
4896
4896
  security_tier: exports_external.enum(["standard", "confidential"]).default("standard"),
4897
- raw_archive: exports_external.boolean().default(false)
4897
+ raw_archive: exports_external.boolean().default(false),
4898
+ research_export: exports_external.boolean().default(false)
4898
4899
  }).default({});
4899
4900
  var NARRATIVE_GUIDANCE_MAX_CHARS = 1500;
4900
4901
  var GUIDANCE_CONTROL = /[\u0000-\u0009\u000B-\u001F\u007F-\u009F]/;
@@ -5721,6 +5722,10 @@ var AdminRawArchiveSetSchema = exports_external.object({ allowed: exports_extern
5721
5722
  var AdminTenantFlagsSchema = exports_external.object({
5722
5723
  tenant: exports_external.object({ id: TenantIdSchema, name: exports_external.string(), internal: exports_external.boolean(), raw_archive: exports_external.boolean() })
5723
5724
  });
5725
+ var AdminResearchExportSetSchema = exports_external.object({ research_export: exports_external.boolean() });
5726
+ var AdminResearchExportFlagSchema = exports_external.object({
5727
+ tenant: exports_external.object({ id: TenantIdSchema, name: exports_external.string(), research_export: exports_external.boolean() })
5728
+ });
5724
5729
  var AdminDeviceVersionSchema = exports_external.object({
5725
5730
  id: DeviceIdSchema,
5726
5731
  name: exports_external.string(),
@@ -7123,6 +7128,14 @@ is required; without one every command answers 403.
7123
7128
  itself off at its next policy read. allow refuses a tenant that is not
7124
7129
  internal and exits 2, and the database refuses it again.
7125
7130
 
7131
+ sixminute-admin research-export allow --env <env> --tenant tenant_... [--json]
7132
+ sixminute-admin research-export revoke --env <env> --tenant tenant_... [--json]
7133
+ Records the firm's WRITTEN instruction to keep research data for it, or
7134
+ withdraws it (policy research_export, false until set). Run allow only
7135
+ on that written instruction. Without it no research card is stored for
7136
+ the firm, from the next completion; revoking deletes no card already
7137
+ stored, which the 30-day purge removes.
7138
+
7126
7139
  sixminute-admin research export --env <env> --tenant tenant_... --from YYYY-MM-DD --to YYYY-MM-DD --out <dir> [--json]
7127
7140
  Unseals one firm's research cards over a day range onto this machine
7128
7141
  and writes two jsonl files in --out: a new folder is created 0700, and
@@ -7510,6 +7523,8 @@ async function runAdmin(argv, deps) {
7510
7523
  return runTierSet(run2);
7511
7524
  if (group === "raw-archive")
7512
7525
  return runRawArchive(run2, subcommand);
7526
+ if (group === "research-export")
7527
+ return runResearchExportFlag(run2, subcommand);
7513
7528
  if (group === "research" && subcommand === "export")
7514
7529
  return runResearchExport(run2);
7515
7530
  if (group === "entries" && subcommand === "purge")
@@ -7616,6 +7631,7 @@ async function runTenantShow(run2) {
7616
7631
  `internal ${t.internal}`,
7617
7632
  `security_tier ${t.security_tier}`,
7618
7633
  `raw_archive ${t.policy.raw_archive}`,
7634
+ `research_export ${t.policy.research_export}`,
7619
7635
  `connector ${t.connector === null ? "none" : `${t.connector.kind} ${t.connector.status}`}`,
7620
7636
  `members ${t.members.active} active of ${t.members.total}`
7621
7637
  ]);
@@ -7633,7 +7649,8 @@ async function runTierSet(run2) {
7633
7649
  `tenant ${tenant.id} ${tenant.name}`,
7634
7650
  `security_tier ${tenant.security_tier}`,
7635
7651
  "",
7636
- "Research cards are stored for this firm for 30 days, sealed under the research key."
7652
+ "Research cards are stored for this firm for 30 days, sealed under the research key, only while it has",
7653
+ "instructed it in writing (research-export allow)."
7637
7654
  ]);
7638
7655
  }
7639
7656
  const deleted = done.cards_deleted ?? 0;
@@ -7685,6 +7702,20 @@ async function runRawArchive(run2, subcommand) {
7685
7702
  allow ? "A person on this tenant can now switch on the raw capture archive on their own device, in Capture settings." : "Every device on this tenant switches its raw archive off at its next policy read."
7686
7703
  ]);
7687
7704
  }
7705
+ async function runResearchExportFlag(run2, subcommand) {
7706
+ if (subcommand !== "allow" && subcommand !== "revoke") {
7707
+ throw new AdminUsageError(`unknown command: research-export ${subcommand ?? ""}`.trim());
7708
+ }
7709
+ const allow = subcommand === "allow";
7710
+ const tenantId = required(run2.flags, "tenant", "which firm's written instruction is being recorded");
7711
+ const { tenant } = AdminResearchExportFlagSchema.parse(expectOk(await call(run2.api, "PUT", tenantPath(tenantId, "/research-export"), { research_export: allow })));
7712
+ return render(run2, { tenant }, [
7713
+ `tenant ${tenant.id} ${tenant.name}`,
7714
+ `research_export ${tenant.research_export}`,
7715
+ "",
7716
+ allow ? "Research cards are stored for this firm from its next completion, for 30 days, sealed under the research key." : "No research card is stored for this firm from its next completion. Cards already stored stay until the 30-day purge."
7717
+ ]);
7718
+ }
7688
7719
  async function runVersions(run2) {
7689
7720
  const tenantId = required(run2.flags, "tenant", "whose devices");
7690
7721
  const found = AdminDeviceVersionListSchema.parse(expectOk(await call(run2.api, "GET", tenantPath(tenantId, "/devices"))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unisonlabs/sixminute-admin",
3
- "version": "0.1.1183-next",
3
+ "version": "0.1.1185-next",
4
4
  "description": "Sixminute operator tool: the admin commands of the Sixminute API, run with your own operator sign-in.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {