@khirby/plugin-pokelo 1.0.1 → 1.1.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": "@khirby/plugin-pokelo",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Khirby — Pokelo RAG knowledge base context for AI Compose",
5
5
  "main": "src/index.ts",
6
6
  "keywords": [
@@ -1,5 +1,5 @@
1
1
  import { Injectable, Logger } from '@nestjs/common';
2
- import type { PokeloContextServiceLike, PokeloFetchOpts } from '../../../packages/plugin-host/src';
2
+ import type { KnowledgeContextLike, PokeloFetchOpts } from '../../../packages/plugin-host/src';
3
3
  import { PokeloSettingsService } from './pokelo-settings.service';
4
4
 
5
5
  const SNIPPET_LIMIT_TOTAL = 8;
@@ -15,7 +15,7 @@ type McpToolResult = {
15
15
  };
16
16
 
17
17
  @Injectable()
18
- export class PokeloContextService implements PokeloContextServiceLike {
18
+ export class PokeloContextService implements KnowledgeContextLike {
19
19
  private readonly logger = new Logger(PokeloContextService.name);
20
20
 
21
21
  constructor(private readonly settings: PokeloSettingsService) {}
@@ -1,60 +1,5 @@
1
- import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
2
-
3
- const ALGORITHM = 'aes-256-gcm';
4
- const IV_BYTES = 12;
5
- const TAG_BYTES = 16;
6
-
7
- function getKey(): Buffer {
8
- const raw = process.env.POKELO_SECRETS_KEY?.trim();
9
- if (!raw) {
10
- throw new Error('POKELO_SECRETS_KEY is not set');
11
- }
12
- let buf: Buffer;
13
- if (/^[0-9a-fA-F]{64}$/.test(raw)) {
14
- buf = Buffer.from(raw, 'hex');
15
- } else {
16
- buf = Buffer.from(raw, 'base64');
17
- }
18
- if (buf.length !== 32) {
19
- throw new Error(
20
- "POKELO_SECRETS_KEY must be 32 bytes as hex (64 chars) or base64 — generate with: node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\"",
21
- );
22
- }
23
- return buf;
24
- }
25
-
26
- export function isPokeloSecretsKeyConfigured(): boolean {
27
- try {
28
- getKey();
29
- return true;
30
- } catch {
31
- return false;
32
- }
33
- }
34
-
35
- /**
36
- * Encrypts plaintext using AES-256-GCM.
37
- * Returns a base64 string: iv(12) + ciphertext + tag(16)
38
- */
39
- export function encrypt(plaintext: string): string {
40
- const key = getKey();
41
- const iv = randomBytes(IV_BYTES);
42
- const cipher = createCipheriv(ALGORITHM, key, iv);
43
- const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
44
- const tag = cipher.getAuthTag();
45
- return Buffer.concat([iv, encrypted, tag]).toString('base64');
46
- }
47
-
48
- /**
49
- * Decrypts a base64 blob produced by `encrypt`.
50
- */
51
- export function decrypt(ciphertext: string): string {
52
- const key = getKey();
53
- const buf = Buffer.from(ciphertext, 'base64');
54
- const iv = buf.subarray(0, IV_BYTES);
55
- const tag = buf.subarray(buf.length - TAG_BYTES);
56
- const encrypted = buf.subarray(IV_BYTES, buf.length - TAG_BYTES);
57
- const decipher = createDecipheriv(ALGORITHM, key, iv);
58
- decipher.setAuthTag(tag);
59
- return decipher.update(encrypted) + decipher.final('utf8');
60
- }
1
+ export {
2
+ decrypt,
3
+ encrypt,
4
+ isInstanceSecretsKeyConfigured as isPokeloSecretsKeyConfigured,
5
+ } from '../../../packages/plugin-host/src/instance-secrets';
@@ -99,7 +99,7 @@ export class PokeloSettingsService {
99
99
  let encryptedToken: string | undefined = undefined;
100
100
  if (dto.token !== undefined && dto.token.trim()) {
101
101
  if (!isPokeloSecretsKeyConfigured()) {
102
- throw AppException.badRequest('POKELO_SECRETS_KEY is not configured');
102
+ throw AppException.badRequest('KHIRBY_SECRETS_KEY is not configured');
103
103
  }
104
104
  encryptedToken = encrypt(dto.token.trim());
105
105
  }
@@ -1,12 +1,12 @@
1
1
  import { Global, Module } from '@nestjs/common';
2
- import { POKELO_CONTEXT_SERVICE } from '../../../packages/plugin-host/src';
2
+ import { KNOWLEDGE_CONTEXT, POKELO_CONTEXT_SERVICE } from '../../../packages/plugin-host/src';
3
3
  import { PokeloSettingsService } from './pokelo-settings.service';
4
4
  import { PokeloContextService } from './pokelo-context.service';
5
5
  import { PokeloSettingsController } from './pokelo-settings.controller';
6
6
 
7
7
  /**
8
- * @Global so AI Compose (sibling plugin module) can @Optional()-inject
9
- * POKELO_CONTEXT_SERVICE (ADR-0022).
8
+ * @Global so sibling plugins can @Optional()-inject KNOWLEDGE_CONTEXT (ADR-0047).
9
+ * POKELO_CONTEXT_SERVICE stays as a second provide until published consumers bump.
10
10
  */
11
11
  @Global()
12
12
  @Module({
@@ -14,8 +14,9 @@ import { PokeloSettingsController } from './pokelo-settings.controller';
14
14
  providers: [
15
15
  PokeloSettingsService,
16
16
  PokeloContextService,
17
+ { provide: KNOWLEDGE_CONTEXT, useExisting: PokeloContextService },
17
18
  { provide: POKELO_CONTEXT_SERVICE, useExisting: PokeloContextService },
18
19
  ],
19
- exports: [POKELO_CONTEXT_SERVICE],
20
+ exports: [KNOWLEDGE_CONTEXT, POKELO_CONTEXT_SERVICE],
20
21
  })
21
22
  export class PokeloModule {}
@@ -7,10 +7,16 @@ describe('pokelo-crypto', () => {
7
7
  const HEX_KEY = 'c'.repeat(64);
8
8
 
9
9
  beforeEach(() => {
10
+ delete process.env.KHIRBY_SECRETS_KEY;
11
+ delete process.env.MAIL_SECRETS_KEY;
12
+ delete process.env.AI_COMPOSE_SECRETS_KEY;
10
13
  process.env.POKELO_SECRETS_KEY = HEX_KEY;
11
14
  });
12
15
 
13
16
  afterEach(() => {
17
+ delete process.env.KHIRBY_SECRETS_KEY;
18
+ delete process.env.MAIL_SECRETS_KEY;
19
+ delete process.env.AI_COMPOSE_SECRETS_KEY;
14
20
  delete process.env.POKELO_SECRETS_KEY;
15
21
  });
16
22
 
@@ -26,9 +32,15 @@ describe('pokelo-crypto', () => {
26
32
  expect(isPokeloSecretsKeyConfigured()).toBe(false);
27
33
  });
28
34
 
35
+ it('isPokeloSecretsKeyConfigured returns true when KHIRBY_SECRETS_KEY is set', () => {
36
+ delete process.env.POKELO_SECRETS_KEY;
37
+ process.env.KHIRBY_SECRETS_KEY = HEX_KEY;
38
+ expect(isPokeloSecretsKeyConfigured()).toBe(true);
39
+ });
40
+
29
41
  it('throws on missing key at encrypt time', () => {
30
42
  delete process.env.POKELO_SECRETS_KEY;
31
- expect(() => encrypt('anything')).toThrow('POKELO_SECRETS_KEY is not set');
43
+ expect(() => encrypt('anything')).toThrow('KHIRBY_SECRETS_KEY is not set');
32
44
  });
33
45
  });
34
46