Skip to content
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,16 @@ See [STATUS.md](server/STATUS.md) to learn more about which features will remain
without `--base-domain`'s other effect of also becoming the store's base
domain (which changes how subjects are normalized and migrated, and is not
something to switch on for a server that already holds data).

- The `/version` and `/all-versions` endpoints are removed. Resource history
is read from the Loro oplog on the client now (`resource.getLoroHistory()`,
with signers from `/history-attribution`), which is what the History route
has used for a while; these endpoints were the older server-side path to the
same data, reachable only from a single "All versions" link. `atomic_lib`
loses `history::encode_version_id` and `history::decode_version_id` with
them -- they existed to carry an opaque `VersionID` through an HTTP query
parameter. `history::versions`, `history::at_version`,
`Resource::get_history` and `Resource::view_at` are unaffected.
- The outbox drains over a live Iroh link too (`sync::peer::LivePeerCommitTransport`):
a device with no hub in reach delivers its queued writes to a paired peer as
signed `COMMIT` frames, which the peer validates and applies like a hub
Expand Down
14 changes: 14 additions & 0 deletions browser/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,20 @@ This changelog covers all five packages, as they are (for now) updated as a whol
- Fix: `Resource.remove()` and `Resource.push()` emit `LocalChange` like `set()` does, so `useValue` / `useArray` re-render when a field is cleared or an item is appended. `useValue`'s setter clears a previously reported validation error when called with `undefined`. `useArray`'s `push` saves through the same debounced scheduler and error handling (`handleValidationError` / `store.notifyError`) as `set`, instead of an immediate `resource.save()` that only logged failures. `StoreContext` no longer defaults to a phantom `Store`: `useStore()` throws when no `<StoreContext.Provider>` is mounted.
- `@tomic/lib`: one list of server-managed properties (`server-managed-props.ts`) replaces the three copies in `resource.ts` and `store.ts` that had drifted apart; the OPFS cold-load guard now also treats an inline `genesis` certificate as skeleton, not content. One serializer (`Resource.toClientDbJsonAd()`) writes the local-database row from both `Store.addResource` and `Resource.persistToClientDb`, and a durable save now records its write in the store's dedup stamp so the next ingress does not rewrite the same row.
- Comment on a table row, like in Notion. Every row's gutter carries a comment bubble: it shows up on hover for a row with nothing on it yet, and stays put — with the count, highlighted while unseen — for a row that has comments. Clicking it opens that row's thread in the Comments panel, headed by the row's title; another row's bubble switches threads, and the same row's closes the panel. A row is a resource of its own, so its thread is the ordinary one (Messages whose `about` points at the row) and needs no setup. The Comments panel can now be aimed at a resource inside the page rather than only at the page's own; the navbar button keeps opening the page's thread.
- Fix: the fork bar no longer fetches the server root on every resource page.
It renders above every resource and only returns `null` for a non-fork after
its hooks have run, so `useResource(originalSubject ?? '')` fired for all of
them; an empty subject resolves against the page origin, which serves no
resource (no Drive is created at `/`), so each page load spent a request on a
404 and logged a console error. It asks for `unknownSubject` instead, which
the store answers from memory without touching the network. This is what made
the `offline-persistence` and `offline-tables` e2e specs fail: they assert on
unexpected browser console errors, and with the WebSocket disconnected the
miss surfaced over HTTP as a logged 404 rather than a silent protocol answer.
- The "All versions" link is gone from the version scroller. It pointed at the
server's `/all-versions` endpoint, which rendered the same history the
scroller was already showing, paginated and without attribution. Both
endpoints behind it are removed.
- Fork bar: "Review changes" opens the per-property diff (the original's current value against the fork's) and names the properties the original also changed since the fork, so a reviewer sees what a merge writes over instead of a count.
- A dashboard is reachable from its table: "Add view" offers **Dashboard**, which creates an empty Dashboard as a child of the table and shows it as a tab (`view-kind: dashboard`, `view-dashboard`). Switching an existing tab to Dashboard does the same. The Dashboard stays a resource of its own, so a Drive page or a document can still embed it.
- Fix: creating a second table column with a name that already exists in the drive's ontology (e.g. two "Status" columns) no longer mints a colliding property shortname that silently corrupts the ontology. A compatible existing property is reused instead; an incompatible one gets a disambiguated shortname (`status-2`) ([#1504](https://github.com/ontola/atomic-server/issues/1504)).
Expand Down
12 changes: 0 additions & 12 deletions browser/data-browser/src/helpers/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,6 @@ export function historyURL(subject: string): string {
return constructURL(paths.history, { subject });
}

/**
* Constructs the URL for the `all-versions` endpoint. Assumes the current URL
* supports that endpoint
*/
export function versionsURL(subject: string, baseURL: string): string {
const url = new URL(baseURL);
url.pathname = paths.allVersions;
url.searchParams.append('subject', subject);

return constructOpenURL(url.toString());
}

/** Takes the cursor position, finds the nearest `about=` attributes in DOM nodes */
export function getSubjectFromDom(): string | null {
const found: string[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ export function HistoryDesktopView({
<VersionScroller
persistSelection
title={`History of ${resource.title}`}
subject={resource.subject}
groupedVersions={groupedVersions}
selectedVersion={selectedVersion}
onSelectVersion={onSelectVersion}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ export function HistoryMobileView({
<>
<CenteredScroller
title={`History of ${resource.title}`}
subject={resource.subject}
groupedVersions={groupedVersions}
selectedVersion={selectedVersion}
onSelectVersion={handleVersionSelect}
Expand Down
23 changes: 1 addition & 22 deletions browser/data-browser/src/routes/History/VersionScroller.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { useId, Fragment, type JSX } from 'react';
import { GroupedVersions } from './HistoryViewProps';
import { Version, useStore } from '@tomic/react';
import { Version } from '@tomic/react';
import { styled } from 'styled-components';
import { Column } from '../../components/Row';
import { VersionButton } from './VersionButton';
import { IconButton } from '../../components/IconButton/IconButton';
import { FaChevronLeft, FaChevronRight } from 'react-icons/fa6';
import { AtomicLink } from '../../components/AtomicLink';
import { versionsURL } from '../../helpers/navigation';

interface VersionScrollerProps {
groupedVersions: GroupedVersions;
selectedVersion: Version | undefined;
subject: string;
onSelectVersion: (version: Version) => void;
onNextItem?: () => void;
onPreviousItem?: () => void;
Expand All @@ -26,13 +23,11 @@ export function VersionScroller({
selectedVersion,
title,
className,
subject,
persistSelection = false,
onNextItem,
onPreviousItem,
onSelectVersion,
}: VersionScrollerProps): JSX.Element {
const store = useStore();
const scrollerTitleId = useId();

return (
Expand Down Expand Up @@ -69,10 +64,6 @@ export function VersionScroller({
</IconButton>
</ButtonWrapper>
)}
<AllVersionsLink path={versionsURL(subject, store.getServerUrl())}>
All versions
<FaChevronRight size='0.9rem' />
</AllVersionsLink>
</ScrollerSection>
);
}
Expand All @@ -88,18 +79,6 @@ const ScrollerSection = styled.section`
position: relative;
`;

const AllVersionsLink = styled(AtomicLink)`
position: absolute;
bottom: -2rem;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5ch;
vertical-align: middle;
line-height: 1;
`;

const Scroller = styled.div`
padding: 1rem;
overflow: auto;
Expand Down
2 changes: 0 additions & 2 deletions browser/data-browser/src/routes/paths.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export const pathNames = {
import: '/import',
onboarding: '/onboarding',
history: '/history',
allVersions: '/all-versions',
sandbox: '/sandbox',
fetchBookmark: '/fetch-bookmark',
pruneTests: '/prunetests',
Expand Down Expand Up @@ -52,7 +51,6 @@ export const paths = {
import: `${pathNames.app}${pathNames.import}`,
onboarding: `${pathNames.app}${pathNames.onboarding}`,
history: `${pathNames.app}${pathNames.history}`,
allVersions: `${pathNames.app}${pathNames.allVersions}`,
sandbox: `${pathNames.app}${pathNames.sandbox}`,
fetchBookmark: pathNames.fetchBookmark,
pruneTests: `${pathNames.app}${pathNames.pruneTests}`,
Expand Down
3 changes: 1 addition & 2 deletions docs/src/interoperability/vc-old.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ This is by design, as storing signed state changes allows for fully verifiable a

If you want to know whether a specific value that you see is signed by a specific Agent, you need to find the Commit that created the value.

This can be achieved by using a Collection.
The easiest way to do this, is by using the [`/all-versions` Endpoint](https://atomicdata.dev/all-versions) and finding the Signer of the version that is relevant to your question.
This can be achieved by using the `/history-attribution` endpoint, which returns the verified signer for each change in a resource's history, as far as this node retained the signed envelopes.

In the near future, we will introduce a `/verify` Endpoint that will allow you to verify a specific value.

Expand Down
28 changes: 0 additions & 28 deletions lib/src/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,9 @@
//!
//! Prefer this over [crate::loro] in app code — it keeps the CRDT details here.

use base64::{engine::general_purpose, Engine};

pub use crate::loro::{VersionID, VersionMetadata};
use crate::{errors::AtomicResult, Resource};

/// A [VersionID] as a URL-safe string, for addressing a version over HTTP.
/// The id is opaque (encoded Loro Frontiers), so it is carried as base64url
/// rather than given a readable structure clients might parse.
pub fn encode_version_id(id: &VersionID) -> String {
general_purpose::URL_SAFE_NO_PAD.encode(id.bytes())
}

pub fn decode_version_id(encoded: &str) -> AtomicResult<VersionID> {
let bytes = general_purpose::URL_SAFE_NO_PAD
.decode(encoded)
.map_err(|e| format!("Not a valid version id: {e}"))?;

Ok(VersionID::from_bytes(bytes))
}

/// The resource's document, as a value this module may read freely.
fn doc_of(resource: &Resource) -> AtomicResult<crate::loro::AtomicLoroDoc> {
let Some(snapshot) = resource.materialized_state() else {
Expand Down Expand Up @@ -160,15 +143,4 @@ mod test {

assert_eq!(versions(&resource).unwrap().len(), 1);
}

#[test]
fn version_ids_survive_a_url() {
let id = VersionID::from_bytes(vec![0, 1, 2, 250, 255]);
let encoded = encode_version_id(&id);
assert!(
!encoded.contains('+') && !encoded.contains('/') && !encoded.contains('='),
"must be URL-safe without padding: {encoded}"
);
assert_eq!(decode_version_id(&encoded).unwrap(), id);
}
}
2 changes: 0 additions & 2 deletions server/src/appstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ impl AppState {
store.add_endpoint(plugins::server_info::server_info_endpoint(
server_info.clone(),
))?;
store.add_endpoint(plugins::versioning::version_endpoint())?;
store.add_endpoint(plugins::versioning::all_versions_endpoint())?;
store.add_endpoint(plugins::did::did_endpoint())?;
store.add_endpoint(plugins::did::resource_endpoint())?;
store.add_endpoint(plugins::did::atomic_endpoint())?;
Expand Down
1 change: 0 additions & 1 deletion server/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ pub mod test_fixture;
pub mod triggers;
#[cfg(feature = "vector-search")]
pub mod vector_search;
pub mod versioning;
pub mod view_token;
#[cfg(feature = "wasm-plugins")]
pub mod wasm;
Expand Down
150 changes: 0 additions & 150 deletions server/src/plugins/versioning.rs

This file was deleted.

Loading