Implement ObjectStack protocol specification with Zod schemas and TypeScript interfaces#3
Merged
Merged
Conversation
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Set up Copilot instructions for ObjectStack
Implement ObjectStack protocol specification with Zod schemas and TypeScript interfaces
Jan 18, 2026
huangyiirene
approved these changes
Jan 18, 2026
Copilot AI
added a commit
that referenced
this pull request
Jan 25, 2026
- Added Chinese meta files for all website protocol sections - Updated references meta files to include website protocol - Updated README to document the 6 core protocol modules - Added Website Protocol as module #3 with preview release date March 2026 Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
xuyushun441-sys
pushed a commit
that referenced
this pull request
May 22, 2026
Introduces an opt-in path in ObjectStackProtocolImplementation.saveMetaItem that writes overlay metadata through SysMetadataRepository.put instead of the raw engine, so writes append to the change-log and emit HMR seq events. Behavioural changes (all behind options.useRepositoryWritePath / OBJECTSTACK_USE_REPOSITORY_WRITE_PATH=1): - saveMetaItem request gained optional parentVersion (If-Match) and actor fields. ConflictError -> 409 metadata_conflict. - Plural type aliases (views, dashboards, ...) normalized to singular before the repo's overlay-allowlist gate (rubber-duck #5). - Object-registry mutation moved AFTER successful put() so a conflict does not leave the in-memory registry stale (rubber-duck #3 invariant test added). Repo/test-fake fixes uncovered by rubber-duck review: - SysMetadataRepository.put/delete now update/delete by row id because the engine's strict .update requires id or multi:true (rubber-duck #1). - sys_metadata.checksum column widened from 64 -> 71 chars to hold the sha256: prefix produced by hashSpec() (rubber-duck #2). - Three test fake engines extended to support both overlay-tuple and id-based where lookups. 333/333 objectql tests pass. Deferred to PR-10d.4: REST plumbing for parentVersion/actor (rubber-duck #6), race-window retry for omitted parentVersion (rubber-duck #4), default flag flip + legacy path removal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
xuyushun441-sys
pushed a commit
that referenced
this pull request
May 23, 2026
…s (PR #3) Resolves the gap left by PR #2: cache + storage adapters accepted an optional MetricsRegistry but their respective Plugin classes never forwarded one, so any host that registered observability via the dispatcher saw zero cache/storage data. Adds: packages/observability/src/service-names.ts OBSERVABILITY_METRICS_SERVICE = 'observability:metrics' OBSERVABILITY_ERRORS_SERVICE = 'observability:errors' packages/runtime/src/observability/observability-service-plugin.ts ObservabilityServicePlugin — registers the host's MetricsRegistry and ErrorReporter under the canonical names. Defaults each to its respective Noop exporter so the services are always present. Also exports resolveMetrics() / resolveErrorReporter() helpers for consumers inside the runtime package. CacheServicePlugin + StorageServicePlugin: - new `metrics?: MetricsRegistry` option (escape hatch for tests) - canonical resolution chain at init(): option override → observability:metrics service → NoopMetricsRegistry - StorageServicePlugin's `buildAdapterFromValues` (the settings live-rebuild path) now also threads metrics into the freshly built adapter, so adapter swaps don't drop instrumentation - log line now reports the resolved registry class name for diagnostics Helpers (resolveMetrics) are inlined as private functions in each service to avoid a circular dep (services must not depend on runtime). Constants live in @objectstack/observability which both services already depend on. New tests: - cache-service-plugin.metrics.test.ts (4 tests, resolution chain + override precedence) - storage-service-plugin.metrics.test.ts (4 tests, incl. settings-rebuild path) - observability-service-plugin.test.ts (3 tests, registration + defaults) All 22 service-cache + 48 service-storage + 282 runtime tests pass (2 pre-existing i18n failures in app-plugin.test.ts on main unchanged). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
6 tasks
xuyushun441-sys
pushed a commit
that referenced
this pull request
May 29, 2026
…s/skills Persist package enable/disable (#2): - SchemaRegistry.setInitialDisabledPackageIds() seeds a disabled-id set that installPackage honors, so every registration path (boot artifact, marketplace rehydrate, local import) applies persisted disable uniformly — no fragile post-boot reapply hook. - New runtime/package-state-store.ts persists the disabled set to <OS_HOME>/package-state/<environmentId>.json, keyed per environment. - AppPlugin.init seeds the registry before the manifest is decomposed. - handlePackages enable/disable persist the new state. Round-trip tools/skills on export & import (#3): - PLURAL_TO_SINGULAR (spec) gains tools->tool, skills->skill (drives export via assemblePackageManifest and the auto-derived reverse map). - engine.registerApp metadataArrayKeys consume tools/skills on import. - metadata ARTIFACT_FIELD_TO_TYPE gains tools->tool (skills already present). - ObjectStackDefinition gains a top-level tools field beside agents/skills. Covers metadata round-trip/visibility; executable ToolRegistry wiring is out of scope. Docs: ADR-0016 §§9.5–9.8 updated (disable now persists; tools/skills round-trip). Verified live: disable -> restart -> stays disabled & app hidden; enable clears state & app returns. registerApp materializes tools/skills. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
xuyushun441-sys
added a commit
that referenced
this pull request
Jun 1, 2026
* feat(spec): structured plugin manifest schema (ADR-0025 F1)
Extend ManifestSchema with the authoritative plugin-distribution shapes
so the cloud control plane can drop its stopgap mirror and import the
canonical schemas.
- PluginPermissionsSchema: structured { services, hooks, network, fs }
(.strict()); ADR-0025 §3.2
- PluginEnginesSchema: { platform, protocol } (protocol-first, §3.10 #3)
- PluginRuntimeSchema: node | sandbox | worker (trust tier, §3.6)
- PluginPackagingSchema: bundled | manifest-deps (§3.3)
- PluginIntegritySchema: Record<path, digest> (§3.2)
ManifestSchema.permissions becomes a backward-compatible union of the
legacy string[] and the structured block; new optional runtime /
packaging / integrity / engines fields added. Legacy engine:{objectstack}
retained and superseded by engines.
Shapes match cloud's stopgap (service-cloud/src/plugin-artifact.ts) so
cloud's swap is a one-line import from @objectstack/spec/kernel.
Verified: tsc clean, 6609 spec tests pass, exports surface in
dist/kernel, runtime parse smoke (legacy + structured + strict reject).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(cli): `os plugin build` + .osplugin packaging (ADR-0025 F2)
Add the build half of the plugin distribution pipeline (ADR-0025 §3.4):
- src/utils/osplugin.ts — dependency-free packaging primitives:
- sriDigest(): canonical per-file integrity string `sha256-<base64>`
(matches ADR §3.2's example; the format cloud/runtime align to).
- computeIntegrity(): builds the manifest `integrity` map (excludes the
manifest itself + SIGNATURE; deterministic key order).
- createTar()/createTarGz(): reproducible ustar+gzip writer (mtime pinned
to 0, sorted entries) so any tar reader can unpack the artifact and
identical inputs yield byte-identical blobs.
- src/commands/plugin/build.ts — `os plugin build`:
1. validate objectstack.plugin.json against the canonical ManifestSchema
(@objectstack/spec/kernel — F1), failing fast with zod diagnostics;
2. esbuild-bundle the entry to dist/index.mjs, externalizing
@objectstack/* (and declared deps for packaging: manifest-deps);
3. compute per-file integrity + emit the compiled manifest;
4. pack dist/ (+assets, +package.json/lockfile for manifest-deps,
+SIGNATURE placeholder) into <id>-<version>.osplugin.
Signing is a separate step; this emits an unsigned artifact.
Tests (6, all green; full CLI suite 143 green): SRI vector, integrity
exclusion+ordering, ustar round-trip with valid checksums, gzip validity,
reproducibility, and an end-to-end build that bundles a fixture plugin and
reads the .osplugin back — exercising F1's schema through the CLI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(core,cli): Ed25519 plugin signature contract + `os plugin sign` (ADR-0025 F3)
Land the canonical signature half of the plugin distribution pipeline,
byte-for-byte aligned with the cloud control plane's package-signing so
the two never drift.
core/src/security/plugin-artifact-signature.ts — the shared Ed25519
detached-signature contract:
- format `ed25519:<keyId>:<base64url>`; sign/verify via node:crypto
(`sign(null,…)`/`verify(null,…)`), keyId as the rotation handle.
- verifyPublisherSignature(): publisher sig over raw artifact bytes,
keyId-resolved key, mirroring cloud's publish-time policy
(no sig → unverified-but-ok; malformed/unknown-key/mismatch → not ok).
- counterSignPayload()/verifyPlatformSignature(): platform counter-sign
over [package_id, version, blob_key, signature].join("\n") — identical
to cloud's payload.
- verifyPluginArtifact(): runs both trust chains at load time
(ADR §3.7); requirePlatform=false for first-party/local builds.
Exported from @objectstack/core/security.
cli plugin/sign.ts — `os plugin sign <artifact> --key <pem> [--key-id]`:
detached publisher signature over the EXACT artifact bytes (the bytes
cloud verifies at publish), written to a `<artifact>.sig` sidecar, with
a self-verify guard. Completes build → sign → publish.
plugin-loader.ts: replace the placeholder verifyPluginSignature with an
honest check — artifact-bytes/counter-sign verification belongs at
materialize time (no artifact bytes exist at loadPlugin()), so the loader
now validates signature well-formedness via parseSignature and fails fast
on a malformed value, pointing at verifyPluginArtifact for the real chains.
Verified: core 269 tests (incl. 14 signature: format, determinism, tamper,
cloud-contract alignment, publisher policy, counter-sign, combined chains,
KeyObject), cli 138 (incl. build→sign→verify e2e against the exact bytes).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(core): enforce install-time granted_permissions (ADR-0025 F4)
Bridge the cloud control plane's persisted consent into runtime
enforcement. `PluginPermissionEnforcer.registerGrantedPermissions()` and
`buildPermissionsFromGrants()` turn the structured grant set cloud writes
to `sys_package_installation.granted_permissions`
(`{ services, hooks, network, fs }`, ADR §3.2) into the runtime
`PluginPermissions` bag that `SecurePluginContext` checks.
Matching: exact value, glob (`*` / `**`), or wildcard `*`; network grants
match the request URL's host; `fs` governs read and write; a null/empty
grant set denies everything (least privilege). This enforces what was
GRANTED at install, not merely what the manifest declared — the right
default for distributed third-party plugins.
Verified: 6 new tests (service/hook/fs/network matching, least-privilege
default, enforcer + SecurePluginContext gating); full core suite 275 green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(spec): plugin fields on uploadArtifact contract (ADR-0025 F5)
Extend UploadArtifactInput/Result so the IPackageService upload path
carries code-bearing `.osplugin` plugins alongside metadata packages,
aligned with the cloud control plane's publish flow:
- Input: `kind` ('metadata' | 'plugin'), detached `signature`
(`ed25519:<keyId>:<base64url>`), `expectedChecksum` (artifact sha256).
- Result: `versionId`, `listingStatus` (e.g. pending_review), and
`signatureVerified`.
All additive + optional — metadata packages are unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Establishes the foundational type system and conventions for the ObjectStack ecosystem. This defines the "Constitution" - shared interfaces, validation schemas, and directory conventions used by ObjectOS, ObjectStudio, ObjectCloud, and third-party plugins.
Core Components
Manifest Schema (
src/schemas/manifest.zod.ts)Plugin Runtime Interface (
src/types/plugin.ts)onInstall,onEnable,onDisablePluginContextprovidesql(ObjectQLClient),os(ObjectOSKernel), andloggerDirectory Conventions (
src/constants/paths.ts)src/schemas,src/triggers,src/client/pages,assetsobjectstack.config.ts,src/index.tsUsage
All types include comprehensive TSDoc for IntelliSense. No runtime dependencies except Zod. Universal compatibility (Node.js/Browser/Electron).
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.