@hasna/knowledge 0.2.25 → 0.2.27

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/README.md CHANGED
@@ -122,6 +122,21 @@ knowledge "How do we cite handbook policy?" --scope project --json
122
122
  HASNA_KNOWLEDGE_WEB_SEARCH=1 open-knowledge web search "latest AI SDK web search" --provider openai --json
123
123
  ```
124
124
 
125
+ ## Guides
126
+
127
+ - [Company wiki workflow](docs/examples/company-wiki-workflow.md): an end-to-end
128
+ local workflow for open-files manifests, search, prompt runs, cited wiki
129
+ pages, linting, reindexing, MCP, and optional hosted/S3 mode.
130
+ - [JSON to SQLite migration](docs/migration/json-to-sqlite.md): how legacy
131
+ JSON notes coexist with the `.hasna/apps/knowledge` workspace and the
132
+ versioned SQLite catalog.
133
+ - [AI-native architecture](docs/architecture/ai-native-knowledge-base.md):
134
+ source boundaries, wiki model, search model, provider registry, and non-goals.
135
+ - [Hybrid semantic search](docs/architecture/hybrid-semantic-search.md):
136
+ keyword/vector/search-context contracts and hosted index options.
137
+ - [Hosted wrapper responsibilities](docs/architecture/hosted-wrapper-responsibilities.md):
138
+ what a future SaaS layer owns outside the OSS package.
139
+
125
140
  ## Commands
126
141
 
127
142
  ### add
@@ -214,10 +229,26 @@ knowledge bucket/prefix while `open-files` remains the source of truth for raw
214
229
  source bytes. The command also reports artifact classes, allowed source ref
215
230
  schemes, and warnings for non-scalable or unsafe config.
216
231
 
232
+ For Hasna XYZ production, the canonical generated-artifact bucket is
233
+ `hasna-xyz-opensource-knowledge-prod` in `us-east-1` with prefix
234
+ `.hasna/apps/knowledge/`. `storage status --json` exposes this under
235
+ `canonical_hasna_xyz` even when local storage is active. The canonical
236
+ metadata-only secret paths are:
237
+
238
+ ```text
239
+ hasna/xyz/opensource/knowledge/prod/env
240
+ hasna/xyz/opensource/knowledge/prod/aws
241
+ hasna/xyz/opensource/knowledge/prod/s3
242
+ ```
243
+
244
+ The future hosted database path, if provisioned, is
245
+ `hasna/xyz/opensource/knowledge/prod/rds`.
246
+
217
247
  ### setup / auth / remote
218
248
  ```bash
219
249
  open-knowledge setup --mode local [--scope project] [--json]
220
250
  open-knowledge setup --mode hosted [--api-url https://knowledge.hasna.xyz] [--scope project] [--json]
251
+ open-knowledge setup --mode hosted --canonical-hasna-xyz [--scope project] [--json]
221
252
  open-knowledge auth login --api-key <key> [--email you@example.com] [--org <slug>] [--scope project] [--json]
222
253
  open-knowledge auth whoami [--scope project] [--json]
223
254
  open-knowledge auth logout [--scope project] [--json]
@@ -503,6 +534,10 @@ prompt, embedding, or agent command explicitly requests a model.
503
534
 
504
535
  Generated knowledge artifacts can be stored locally under
505
536
  `.hasna/apps/knowledge/artifacts` or through the S3 artifact-store adapter.
537
+ For Hasna XYZ production, `open-knowledge setup --mode hosted
538
+ --canonical-hasna-xyz --scope project --json` configures generated artifacts
539
+ under `s3://hasna-xyz-opensource-knowledge-prod/.hasna/apps/knowledge/` and
540
+ keeps `open-files` as the raw-source owner.
506
541
 
507
542
  The default safety policy allows writes only under the resolved
508
543
  `.hasna/apps/knowledge` workspace. S3 manifest/outbox reads require
@@ -13660,7 +13660,7 @@ import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync
13660
13660
  // package.json
13661
13661
  var package_default = {
13662
13662
  name: "@hasna/knowledge",
13663
- version: "0.2.25",
13663
+ version: "0.2.27",
13664
13664
  description: "Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions",
13665
13665
  type: "module",
13666
13666
  bin: {
@@ -13731,6 +13731,42 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
13731
13731
  import { homedir } from "os";
13732
13732
  import { dirname, join, resolve } from "path";
13733
13733
  var HASNA_KNOWLEDGE_APP_PATH = join(".hasna", "apps", "knowledge");
13734
+ var HASNA_XYZ_KNOWLEDGE_CANONICAL = {
13735
+ division: "xyz",
13736
+ app_type: "opensource",
13737
+ app: "knowledge",
13738
+ env: "prod",
13739
+ local_path: HASNA_KNOWLEDGE_APP_PATH,
13740
+ s3: {
13741
+ bucket: "hasna-xyz-opensource-knowledge-prod",
13742
+ region: "us-east-1",
13743
+ profile: "hasna-xyz-infra",
13744
+ prefix: ".hasna/apps/knowledge",
13745
+ server_side_encryption: "AES256"
13746
+ },
13747
+ secrets: {
13748
+ env: "hasna/xyz/opensource/knowledge/prod/env",
13749
+ aws: "hasna/xyz/opensource/knowledge/prod/aws",
13750
+ s3: "hasna/xyz/opensource/knowledge/prod/s3",
13751
+ rds: null,
13752
+ future_rds: "hasna/xyz/opensource/knowledge/prod/rds"
13753
+ },
13754
+ source_owner: "open-files",
13755
+ evidence_doc: "docs/canonical-secrets-bootstrap-2026-06-08.md"
13756
+ };
13757
+ function canonicalHasnaXyzKnowledgeStorage() {
13758
+ return {
13759
+ type: "s3",
13760
+ artifacts_root: "artifacts",
13761
+ s3: {
13762
+ bucket: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.bucket,
13763
+ prefix: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.prefix,
13764
+ region: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.region,
13765
+ profile: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.profile,
13766
+ server_side_encryption: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.server_side_encryption
13767
+ }
13768
+ };
13769
+ }
13734
13770
  function legacyGlobalStorePath() {
13735
13771
  return join(homedir(), ".open-knowledge", "db.json");
13736
13772
  }
@@ -18115,6 +18151,9 @@ function resolveStorageContract(config2, workspace, scope = "global") {
18115
18151
  const s3 = config2.storage.s3 ?? null;
18116
18152
  const prefix = s3?.prefix?.replace(/^\/+|\/+$/g, "") ?? "";
18117
18153
  const s3UriPrefix = s3 ? `s3://${s3.bucket}/${prefix ? `${prefix}/` : ""}` : "";
18154
+ const canonicalPrefix = HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.prefix.replace(/^\/+|\/+$/g, "");
18155
+ const canonicalS3UriPrefix = `s3://${HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.bucket}/${canonicalPrefix}/`;
18156
+ const canonicalActive = config2.storage.type === "s3" && s3?.bucket === HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.bucket && (s3.region ?? null) === HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.region;
18118
18157
  return {
18119
18158
  scope,
18120
18159
  mode: config2.mode,
@@ -18149,6 +18188,30 @@ function resolveStorageContract(config2, workspace, scope = "global") {
18149
18188
  kms_key_configured: Boolean(s3.kms_key_id)
18150
18189
  } : null
18151
18190
  },
18191
+ canonical_hasna_xyz: {
18192
+ division: HASNA_XYZ_KNOWLEDGE_CANONICAL.division,
18193
+ app_type: HASNA_XYZ_KNOWLEDGE_CANONICAL.app_type,
18194
+ app: HASNA_XYZ_KNOWLEDGE_CANONICAL.app,
18195
+ env: HASNA_XYZ_KNOWLEDGE_CANONICAL.env,
18196
+ active: canonicalActive,
18197
+ local_path: HASNA_XYZ_KNOWLEDGE_CANONICAL.local_path,
18198
+ s3: {
18199
+ bucket: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.bucket,
18200
+ region: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.region,
18201
+ profile: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.profile,
18202
+ prefix: canonicalPrefix,
18203
+ uri_prefix: canonicalS3UriPrefix,
18204
+ server_side_encryption: HASNA_XYZ_KNOWLEDGE_CANONICAL.s3.server_side_encryption
18205
+ },
18206
+ secrets: {
18207
+ env: HASNA_XYZ_KNOWLEDGE_CANONICAL.secrets.env,
18208
+ aws: HASNA_XYZ_KNOWLEDGE_CANONICAL.secrets.aws,
18209
+ s3: HASNA_XYZ_KNOWLEDGE_CANONICAL.secrets.s3,
18210
+ rds: HASNA_XYZ_KNOWLEDGE_CANONICAL.secrets.rds,
18211
+ future_rds: HASNA_XYZ_KNOWLEDGE_CANONICAL.secrets.future_rds
18212
+ },
18213
+ evidence_doc: HASNA_XYZ_KNOWLEDGE_CANONICAL.evidence_doc
18214
+ },
18152
18215
  hosted: {
18153
18216
  enabled: config2.mode === "hosted",
18154
18217
  api_url: normalizeKnowledgeApiOrigin(config2.hosted?.api_url ?? DEFAULT_KNOWLEDGE_API_URL),
@@ -19058,16 +19121,21 @@ class KnowledgeService {
19058
19121
  hosted: {
19059
19122
  ...current.hosted ?? {},
19060
19123
  ...apiUrl ? { api_url: apiUrl } : {}
19061
- }
19124
+ },
19125
+ storage: options.canonicalHasnaXyz ? canonicalHasnaXyzKnowledgeStorage() : current.storage
19062
19126
  };
19063
19127
  writeKnowledgeConfig(workspace.configPath, nextConfig);
19064
19128
  this.cachedConfig = nextConfig;
19129
+ const storage = resolveStorageContract(nextConfig, workspace, this.scope);
19065
19130
  return {
19066
19131
  ok: true,
19067
19132
  mode,
19068
19133
  api_url: nextConfig.hosted?.api_url ?? null,
19134
+ storage_type: nextConfig.storage.type,
19135
+ artifact_uri_prefix: storage.artifact_store.uri_prefix,
19136
+ canonical_hasna_xyz: storage.canonical_hasna_xyz,
19069
19137
  config_path: workspace.configPath,
19070
- next: mode === "hosted" ? ["open-knowledge auth login --api-key <key>", "open-knowledge remote contracts --json"] : ["open-knowledge search <query>", "knowledge <prompt>"],
19138
+ next: mode === "hosted" ? ["open-knowledge auth login --api-key <key>", "open-knowledge storage status --json", "open-knowledge remote contracts --json"] : ["open-knowledge search <query>", "knowledge <prompt>"],
19071
19139
  message: `Set knowledge mode to ${mode}`
19072
19140
  };
19073
19141
  }