Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,21 @@ OneWorks license and provenance details are in `THIRD_PARTY_NOTICES.md`. Local
experimental Host, Protocol, and Avatar checkpoints may be used for combination
validation; that does not make them a merged or released dependency.

## Plugin artwork and distribution

The selected 256×256 brand artwork is tracked at `assets/chatroom.png` and
included in the package file allowlist. The plugin entry exports `icon` through
the public `CordisXPluginBrandIcon` contract (`mediaType` and base64 `data`).
The Host validates this local artwork and renders it in its plugin list and
details; action and navigation icons continue to use Host semantic tokens.
`test/brand-icon.mjs` verifies the PNG digest, dimensions, embedded bytes, and
production graph inclusion.

Chatroom remains a private npm package with `explicit-local-v1` distribution.
This artwork ships through the repository source and the normal built local
package; no npm release or new version is required. Marketplace artwork can
reference `assets/chatroom.png` at an immutable repository commit.

## License

[MIT](LICENSE)
Expand Down
Binary file added assets/chatroom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"main": "./dist/runtime/chatroom.js",
"types": "./dist/chatroom.d.ts",
"files": [
"assets/chatroom.png",
"dist",
"entities",
"cordisx-package.json",
Expand Down
8 changes: 8 additions & 0 deletions src/chatroom-brand-icon.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/chatroom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ export type ChatroomMessages =
'permission.approvals.decide': undefined;
};

export { icon } from './chatroom-brand-icon.js';
export { Config, configApplies };
export { manifest, roomSessionDetailRoute };

Expand Down
29 changes: 29 additions & 0 deletions test/brand-icon.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import assert from 'node:assert/strict';
import { createHash } from 'node:crypto';
import { readFile } from 'node:fs/promises';
import { test } from 'node:test';
import { icon } from '../dist/chatroom-brand-icon.js';

test('brand artwork preserves the selected PNG in the public module icon and runtime graph', async () => {
const png = await readFile(new URL('../assets/chatroom.png', import.meta.url));
assert.equal(
createHash('sha256').update(png).digest('hex'),
'6cfaaac15f1e7d325f2db248aaf28981c22460797f090ba30fc558a54d711620',
);
assert.equal(png.readUInt32BE(16), 256);
assert.equal(png.readUInt32BE(20), 256);
assert.equal(icon.mediaType, 'image/png');
assert.deepEqual(Buffer.from(icon.data, 'base64'), png);
assert.ok(icon.data.length <= 400_000);
const entry = await readFile(new URL('../dist/chatroom.js', import.meta.url), 'utf8');
assert.match(entry, /export \{ icon \} from '\.\/chatroom-brand-icon\.js'/u);
const artifact = JSON.parse(await readFile(new URL('../dist/runtime/artifact.json', import.meta.url), 'utf8'));
const modules = await Promise.all(
artifact.files.filter(file => file.kind === 'module').map(file =>
readFile(new URL(`../dist/runtime/${file.path.slice(2)}`, import.meta.url), 'utf8')
),
);
assert.ok(modules.some(module => module.includes(icon.data)), 'runtime graph retains the embedded PNG');
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
assert.ok(packageJson.files.includes('assets/chatroom.png'));
});
Loading