diff --git a/.github/workflows/words-to-ignore.txt b/.github/workflows/words-to-ignore.txt index 73ee8ef..6bb1869 100644 --- a/.github/workflows/words-to-ignore.txt +++ b/.github/workflows/words-to-ignore.txt @@ -79,6 +79,8 @@ codec backlink like link prepend like append preimage like image +UTF +URI # rationale Combinatoric diff --git a/README.md b/README.md index 338d7a0..29d2b6f 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ The WNFS spec is a suite of specifications consisting of public WNFS, private WN The specifications are: - [Public WNFS](/spec/public-wnfs.md) - [Private WNFS](/spec/private-wnfs.md) +- [Symlinks in WNFS](/spec/symlinks.md) - [Namefilters](/spec/namefilter.md) - [Skip Ratchet](/spec/skip-ratchet.md) ## Editors diff --git a/spec/public-wnfs.md b/spec/public-wnfs.md index b9bf85b..20cef3a 100644 --- a/spec/public-wnfs.md +++ b/spec/public-wnfs.md @@ -9,8 +9,6 @@ Nodes need to be encoded as dag-cbor. A directory node contains a map of entry names to either symlinks or CIDs that resolve to another directory or to a file. ```typescript -type PublicRoot = CBOR - type PublicNode = PublicDirectory | PublicFile @@ -21,11 +19,7 @@ type PublicDirectory = { previous: Array>> // userland: metadata: Metadata - entries: Record> | PublicSymlink> -} - -type PublicSymlink = { - ipns: string // e.g. alice.files.fission.name/public/ + entries: Record> | Symlink> } type PublicFile = { @@ -38,6 +32,8 @@ type PublicFile = { } ``` +Symbolic links (`Symlink`s) are described in the [Symlink Specification](/spec/symlinks.md). + ## Metadata The metadata field MUST be a CBOR map. It is in userland, and contains arbitrary keys and values. diff --git a/spec/symlinks.md b/spec/symlinks.md new file mode 100644 index 0000000..4804bb2 --- /dev/null +++ b/spec/symlinks.md @@ -0,0 +1,118 @@ +# Symlink Specification + +Symlink is short for "Symbolic Link". + +# 0 Abstract + +Symlinks are a tool for users to organize their file system: +- They allow linking to the same directory from different places in their file system +- They enable linking out to other user's file systems from your own file system +- They enable linking between public and private parts of file systems + +While hard links (`CID`s or private references) conceptually are supposed to work like 'copying' the linked data, a symlink is meant to work differently: +- It won't guarantee availability. +- It's mutable: Resolving the same link twice may result in different results. +- It doesn't provide integrity of the linked data on its own. + +Symlinks shouldn't be confused with a key management mechanism: Knowing a symlink doesn't provide additional read or write access. This ensures the conceptual invariant that giving someone read or write access to a directory will only give them access to that directory and anything contained in it. Symlinks are not meant to 'contain' the data they link to, as that may change over time. + +# 1 Layout + +Because of differences in addressing between public and private WNFS, symlinks have different formats depending on whether you're linking into public or linking into private data. + +```ts +type Symlink = PublicSymlink | PrivateSymlink +``` + +Symlinks are objects containing a `type` key set to either `"wnfs/sym/pub"`, if it's a public symlink or `"wnfs/sym/priv"`, if it's a private symlink. + +We call symlinks that refer to some data that is external to the current WNFS 'foreign'. Foreign symlinks MUST include a `root` pointer to the root they're relative to. + +## 1.1 Public Symlink + +```ts +type PublicSymlink = { + type: "wnfs/sym/pub" + root?: string + path: string[] +} +``` + +Public data is symlinked via a list of [UTF-8](https://www.rfc-editor.org/rfc/rfc3629) path segment strings. + +If the symlink is not linking relative to the same file system, it can provide a `root` parameter: An [`ipns://` URI](https://github.com/ipfs/in-web-browsers/blob/master/ADDRESSING.md) to the public root that the path is relative to. + +A foreign public symlink's `root` MUST point to a [public directory](/spec/public-wnfs.md). + +### 1.1.1 Public Symlink Examples + +```json +{ + "type": "wnfs/sym/pub", + "root": "ipns://matheus23.files.fission.name/public/", + "path": ["Profile", "Avatar.jpg"] +} +``` + +```json +{ + "type": "wnfs/sym/pub", + "path": ["Documents", "Notes.md"] +} +``` + +```json +{ + "type": "wnfs/sym/pub", + "root": "ipns://matheus23.files.fission.name/public/", + "path": [] +} +``` + +```json +{ + "type": "wnfs/sym/pub", + "root": "ipns://k51qzi5uqu5dgutdk6i1ynyzgkqngpha5xpgia3a5qqp4jsh0u4csozksxel2r/public/", + "path": [] +} +``` + +## 1.2 Private Symlink + +```ts +type PrivateSymlink = { + type: "wnfs/sym/priv" + root?: string + inumber: Inumber +} +``` + +A private symlink identifies a private node via its `inumber`. + +A foreign private symlink's `root` MUST point to a [private forest](/spec/private-wnfs.md#21-ciphertext-blocks). + +### 1.2.1 Private Symlink Examples + +```json +{ + "type": "wnfs/sym/priv", + "root": "ipns://matheus23.files.fission.name/private", + "inumber": +} +``` + +```json +{ + "type": "wnfs/sym/priv", + "inumber": +} +``` + +```json +{ + "type": "wnfs/sym/priv", + "root": "ipns://k51qzi5uqu5dgutdk6i1ynyzgkqngpha5xpgia3a5qqp4jsh0u4csozksxel2r/private/", + "inumber": +} +``` +