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
21 changes: 0 additions & 21 deletions .changeset/lazy-hounds-search.md

This file was deleted.

51 changes: 0 additions & 51 deletions .changeset/quiet-pandas-tickle.md

This file was deleted.

55 changes: 55 additions & 0 deletions packages/adapter-api/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,60 @@
# @haverstack/adapter-api

## 0.13.0

### Minor Changes

- [#207](https://github.com/haverstack/core/pull/207) [`7db6eaf`](https://github.com/haverstack/core/commit/7db6eaff9dd96eccbc9e96e7a104f3529aa708c9) Thanks [@cuibonobo](https://github.com/cuibonobo)! - Relationship associations carry a discriminated `target` instead of a bare `recordId`

A relationship's target now names which identifier space its value belongs to:
`{ scope: 'record', recordId, stackUrl? }` for a Record here or in another stack,
`{ scope: 'entity', entityId }` for a DID, and `{ scope: 'external', ns, id }` for
anything outside the stack — an ATProto post, an ActivityPub actor, an email address,
a URL. Core expresses the reference and never dereferences it, so no protocol is
privileged.

The `entity` arm closes a gap in the identity model rather than only enabling external
references: group rosters stored member DIDs in a field typed `RecordId`, and the
permission path compared the two as plain strings. A roster entry carrying a `record`
target now confers nothing, even when its value equals a member's DID.

`RecordFilter.relatedTo` moves with it. It names a label, a target, or both, and each
is a pattern: a bare `label` matches every target under it, and an external target with
no `id` matches a whole namespace. A `record` target with no `stackUrl` matches only
local targets — absence names this stack rather than acting as a wildcard. Label-only
and namespace-wide queries were not expressible before. "Carries any relationship at
all" is deliberately not expressible, in line with `tags` and `hasAttachment`, which
have no match-any form either.

Reference-creation gating now applies only to a relationship naming a Record in this
stack; the other arms name nothing core can resolve, so there is no access for the
gate to protect. The SQLite association table gains `related_scope`, `related_ns` and
`related_stack` columns, all part of the primary key — so two copies of one record on
two networks are two associations rather than a silent no-op. Existing stack files
predate those columns and must be recreated.

Over the wire, the relationship filter's scope is implied by which parameters appear
(`relatedTo`/`relatedToStack`, `relatedToEntity`, or `relatedToNs`/`relatedToId`), and
a request mixing scopes is rejected with 400. At least one is always present, so the
filter cannot encode to an empty query string and widen the query it meant to narrow.

A target names exactly one thing, exactly one way, and both halves are enforced at
runtime rather than only by the type — a target reaching a server in a request body,
or a filter decoded from query parameters, is a plain object the type never saw. A
`scope` outside the three, or an empty string where a target names something, is
rejected with `StackValidationError`; a `relatedTo` naming neither a label nor a target
is rejected with `StackQueryError` instead of matching every Record carrying a
relationship. This stack is named by omitting `stackUrl`, never by sending an empty
one: storage, association identity and the filter all read absent and empty as this
stack, and reference-creation gating now reads them that way too, so both spellings of
a local Record require read access to it.

### Patch Changes

- Updated dependencies [[`7db6eaf`](https://github.com/haverstack/core/commit/7db6eaff9dd96eccbc9e96e7a104f3529aa708c9)]:
- @haverstack/wire-types@0.13.0
- @haverstack/core@0.14.0

## 0.12.2

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@haverstack/adapter-api",
"version": "0.12.2",
"version": "0.13.0",
"description": "Remote server adapter for Haverstack",
"type": "module",
"exports": {
Expand Down
13 changes: 13 additions & 0 deletions packages/adapter-local/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# @haverstack/adapter-local

## 0.13.0

### Minor Changes

- Released for a breaking change in `@haverstack/blob-adapter-disk`, `@haverstack/core`, `@haverstack/record-adapter-sqlite`.

### Patch Changes

- Updated dependencies [[`d69e53b`](https://github.com/haverstack/core/commit/d69e53b287394c968b960beafdda27d1123f8386), [`7db6eaf`](https://github.com/haverstack/core/commit/7db6eaff9dd96eccbc9e96e7a104f3529aa708c9)]:
- @haverstack/blob-adapter-disk@0.12.0
- @haverstack/record-adapter-sqlite@0.6.0
- @haverstack/core@0.14.0

## 0.12.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-local/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@haverstack/adapter-local",
"version": "0.12.0",
"version": "0.13.0",
"description": "Local (SQLite + disk) stack adapter for Haverstack",
"type": "module",
"engines": {
Expand Down
11 changes: 11 additions & 0 deletions packages/blob-adapter-disk/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# @haverstack/blob-adapter-disk

## 0.12.0

### Minor Changes

- Released for a breaking change in `@haverstack/core`.

### Patch Changes

- Updated dependencies [[`7db6eaf`](https://github.com/haverstack/core/commit/7db6eaff9dd96eccbc9e96e7a104f3529aa708c9)]:
- @haverstack/core@0.14.0

## 0.11.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/blob-adapter-disk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@haverstack/blob-adapter-disk",
"version": "0.11.0",
"version": "0.12.0",
"description": "Disk blob adapter for Haverstack",
"type": "module",
"exports": {
Expand Down
11 changes: 11 additions & 0 deletions packages/commons/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# @haverstack/commons

## 0.6.0

### Minor Changes

- Released for a breaking change in `@haverstack/core`.

### Patch Changes

- Updated dependencies [[`7db6eaf`](https://github.com/haverstack/core/commit/7db6eaff9dd96eccbc9e96e7a104f3529aa708c9)]:
- @haverstack/core@0.14.0

## 0.5.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/commons/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@haverstack/commons",
"version": "0.5.0",
"version": "0.6.0",
"description": "Canonical Schema Commons type definitions for Haverstack — register commons types exactly as written",
"type": "module",
"exports": {
Expand Down
54 changes: 54 additions & 0 deletions packages/conformance-fixtures/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,59 @@
# @haverstack/conformance-fixtures

## 0.7.0

### Minor Changes

- [#207](https://github.com/haverstack/core/pull/207) [`7db6eaf`](https://github.com/haverstack/core/commit/7db6eaff9dd96eccbc9e96e7a104f3529aa708c9) Thanks [@cuibonobo](https://github.com/cuibonobo)! - Relationship associations carry a discriminated `target` instead of a bare `recordId`

A relationship's target now names which identifier space its value belongs to:
`{ scope: 'record', recordId, stackUrl? }` for a Record here or in another stack,
`{ scope: 'entity', entityId }` for a DID, and `{ scope: 'external', ns, id }` for
anything outside the stack — an ATProto post, an ActivityPub actor, an email address,
a URL. Core expresses the reference and never dereferences it, so no protocol is
privileged.

The `entity` arm closes a gap in the identity model rather than only enabling external
references: group rosters stored member DIDs in a field typed `RecordId`, and the
permission path compared the two as plain strings. A roster entry carrying a `record`
target now confers nothing, even when its value equals a member's DID.

`RecordFilter.relatedTo` moves with it. It names a label, a target, or both, and each
is a pattern: a bare `label` matches every target under it, and an external target with
no `id` matches a whole namespace. A `record` target with no `stackUrl` matches only
local targets — absence names this stack rather than acting as a wildcard. Label-only
and namespace-wide queries were not expressible before. "Carries any relationship at
all" is deliberately not expressible, in line with `tags` and `hasAttachment`, which
have no match-any form either.

Reference-creation gating now applies only to a relationship naming a Record in this
stack; the other arms name nothing core can resolve, so there is no access for the
gate to protect. The SQLite association table gains `related_scope`, `related_ns` and
`related_stack` columns, all part of the primary key — so two copies of one record on
two networks are two associations rather than a silent no-op. Existing stack files
predate those columns and must be recreated.

Over the wire, the relationship filter's scope is implied by which parameters appear
(`relatedTo`/`relatedToStack`, `relatedToEntity`, or `relatedToNs`/`relatedToId`), and
a request mixing scopes is rejected with 400. At least one is always present, so the
filter cannot encode to an empty query string and widen the query it meant to narrow.

A target names exactly one thing, exactly one way, and both halves are enforced at
runtime rather than only by the type — a target reaching a server in a request body,
or a filter decoded from query parameters, is a plain object the type never saw. A
`scope` outside the three, or an empty string where a target names something, is
rejected with `StackValidationError`; a `relatedTo` naming neither a label nor a target
is rejected with `StackQueryError` instead of matching every Record carrying a
relationship. This stack is named by omitting `stackUrl`, never by sending an empty
one: storage, association identity and the filter all read absent and empty as this
stack, and reference-creation gating now reads them that way too, so both spellings of
a local Record require read access to it.

### Patch Changes

- Updated dependencies []:
- @haverstack/wire-types@0.13.0

## 0.6.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/conformance-fixtures/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@haverstack/conformance-fixtures",
"version": "0.6.0",
"version": "0.7.0",
"description": "Request/response fixtures for the Stack API wire protocol, shared between adapter-api and server implementations",
"type": "module",
"exports": {
Expand Down
49 changes: 49 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,54 @@
# @haverstack/core

## 0.14.0

### Minor Changes

- [#207](https://github.com/haverstack/core/pull/207) [`7db6eaf`](https://github.com/haverstack/core/commit/7db6eaff9dd96eccbc9e96e7a104f3529aa708c9) Thanks [@cuibonobo](https://github.com/cuibonobo)! - Relationship associations carry a discriminated `target` instead of a bare `recordId`

A relationship's target now names which identifier space its value belongs to:
`{ scope: 'record', recordId, stackUrl? }` for a Record here or in another stack,
`{ scope: 'entity', entityId }` for a DID, and `{ scope: 'external', ns, id }` for
anything outside the stack — an ATProto post, an ActivityPub actor, an email address,
a URL. Core expresses the reference and never dereferences it, so no protocol is
privileged.

The `entity` arm closes a gap in the identity model rather than only enabling external
references: group rosters stored member DIDs in a field typed `RecordId`, and the
permission path compared the two as plain strings. A roster entry carrying a `record`
target now confers nothing, even when its value equals a member's DID.

`RecordFilter.relatedTo` moves with it. It names a label, a target, or both, and each
is a pattern: a bare `label` matches every target under it, and an external target with
no `id` matches a whole namespace. A `record` target with no `stackUrl` matches only
local targets — absence names this stack rather than acting as a wildcard. Label-only
and namespace-wide queries were not expressible before. "Carries any relationship at
all" is deliberately not expressible, in line with `tags` and `hasAttachment`, which
have no match-any form either.

Reference-creation gating now applies only to a relationship naming a Record in this
stack; the other arms name nothing core can resolve, so there is no access for the
gate to protect. The SQLite association table gains `related_scope`, `related_ns` and
`related_stack` columns, all part of the primary key — so two copies of one record on
two networks are two associations rather than a silent no-op. Existing stack files
predate those columns and must be recreated.

Over the wire, the relationship filter's scope is implied by which parameters appear
(`relatedTo`/`relatedToStack`, `relatedToEntity`, or `relatedToNs`/`relatedToId`), and
a request mixing scopes is rejected with 400. At least one is always present, so the
filter cannot encode to an empty query string and widen the query it meant to narrow.

A target names exactly one thing, exactly one way, and both halves are enforced at
runtime rather than only by the type — a target reaching a server in a request body,
or a filter decoded from query parameters, is a plain object the type never saw. A
`scope` outside the three, or an empty string where a target names something, is
rejected with `StackValidationError`; a `relatedTo` naming neither a label nor a target
is rejected with `StackQueryError` instead of matching every Record carrying a
relationship. This stack is named by omitting `stackUrl`, never by sending an empty
one: storage, association identity and the filter all read absent and empty as this
stack, and reference-creation gating now reads them that way too, so both spellings of
a local Record require read access to it.

## 0.13.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@haverstack/core",
"version": "0.13.1",
"version": "0.14.0",
"description": "Core library for Haverstack — portable personal data stack",
"type": "module",
"exports": {
Expand Down
Loading
Loading