{"id":20770517,"url":"https://github.com/ably/features","last_synced_at":"2025-09-02T16:37:13.408Z","repository":{"id":44542169,"uuid":"512812478","full_name":"ably/features","owner":"ably","description":"The Ably canonical features list. SDK Team. Incubating.","archived":false,"fork":false,"pushed_at":"2024-03-13T02:41:42.000Z","size":1212,"stargazers_count":5,"open_issues_count":10,"forks_count":1,"subscribers_count":25,"default_branch":"main","last_synced_at":"2025-04-18T01:24:06.965Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://sdk.ably.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ably.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-11T15:31:15.000Z","updated_at":"2023-07-24T11:43:48.000Z","dependencies_parsed_at":"2022-07-19T04:02:08.206Z","dependency_job_id":null,"html_url":"https://github.com/ably/features","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ably%2Ffeatures","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ably%2Ffeatures/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ably%2Ffeatures/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ably%2Ffeatures/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ably","download_url":"https://codeload.github.com/ably/features/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251714589,"owners_count":21631753,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T12:10:02.834Z","updated_at":"2025-04-30T13:49:19.849Z","avatar_url":"https://github.com/ably.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ably Features\n\n[![Check](https://github.com/ably/features/actions/workflows/check.yml/badge.svg)](https://github.com/ably/features/actions/workflows/check.yml)\n[![Assemble](https://github.com/ably/features/actions/workflows/assemble.yml/badge.svg)](https://github.com/ably/features/actions/workflows/assemble.yml)\n\n_[Ably](https://ably.com) is the platform that powers synchronized digital experiences in realtime. Whether attending an event in a virtual venue, receiving realtime financial information, or monitoring live car performance data – consumers simply expect realtime digital experiences as standard. Ably provides a suite of APIs to build, extend, and deliver powerful digital experiences in realtime for more than 250 million devices across 80 countries each month. Organizations like Bloomberg, HubSpot, Verizon, and Hopin depend on Ably’s platform to offload the growing complexity of business-critical realtime data synchronization at global scale. For more information, see the [Ably documentation](https://ably.com/docs)._\n\n## Overview\n\nThis repository is the starting point and canonical root for information relating to how we programmatically track Ably features at Ably.\nThe focus of the contents of this repository is on our SDKs (sometimes referred to as client libraries).\nOur SDKs provide the primary, language/platform-idiomatic APIs that our customers - software application developers -\nuse in order to integrate and leverage the Ably platform in their solutions.\n\n---\n\n:warning: **Incubating** :warning:  \nThe contents of this repository (state of `HEAD` of `main` branch) are currently in a [`pre-release` state](https://semver.org/#spec-item-9), hence the `-alpha` suffix on the value of the `version` field in [package.json](package.json).  \nThis will change once all of the issues under [the **1.2.0 Release / GA** milestone](https://github.com/ably/features/milestone/1) have been completed. See the description on that milestone for more detail.\n\n---\n\n## Introduction\n\nThe data and code files in this repository are incubating as a prototype, formulating the foundations of Ably's approach to SDK feature tracking going forwards.\n\nWithin the data and code files in this repository, these are the pivotal components:\n\n| Component | Purpose |\n| ---- | ------- |\n| [`sdk.yaml`](sdk.yaml) | The canonical feature list that Ably SDKs can support, represented as a tree. |\n| [`sdk-manifests/`](sdk-manifests/) | Temporary location (while we prototype) for manifests, per SDK source code repository, declaring what features that SDK supports. These files will ultimately be moved to be managed as peer-level source code in each SDK's source code repository. |\n| [`build.js`](render/build.js) | Proof-of-concept build tool. The primary purposes of this program, for the time being, are to: (1) validate the structure of data files - canonical feature list and SDK manifest(s); and (2) render a view of the data to enhance understanding and demonstrate utility, both present and potential. |\n\nThis document aims to not duplicate information that readers/reviewers can gain for themselves by inspecting the source code of the components described in the table above.\nIt does, however, aim to expand on concepts and append context - with the hope that this will help readers/reviewers understand the reasons behind design choices made.\n\n## Usage\n\nWhen we make a new release for this repository we create a new version tag.\nDownstream users can obtain [`sdk.yaml`](sdk.yaml) at a specific version using its GitHub raw URL.\n\nFor example version `1.2.3` can be obtained from:\n\n    https://github.com/ably/features/raw/v1.2.3/sdk.yaml\n\n## Future Direction\n\n### Future Direction for the SDK Manifests\n\nAs mentioned in [the Introduction to this document](#introduction),\n[the manifest source files]((sdk-manifests/))\nare only in this repository right now on a temporary basis while we incubate this prototype.\n\nThey will be moved to the SDK repositories to which they pertain, to be managed as source code in that location, allowing for them to be atomically evolved alongside the interface and implementation source code that they document.\n\nOnce they've moved, they will be treated as first-class citizens in their SDK repository homes. It will be a requirement that we run checks in CI, within each SDK repository, that validate that SDK's manifest against the canonical feature list - hence the `common-version` root node in manifests, as this will need to be anchored to allow the content of _this_ repository (`ably/features`) to evolve independently.\n\nWithin the contents of each SDK repository, the manifest files will be located under a standard filename, in a standard location:\n\n- Location: `.ably/`\n- Filename: `capabilities.yaml`\n\n:magic_wand: At that point, it is anticipated that the real magic can start...\n\n#### Per-SDK Magic\n\n- **Key Information, Front and Centre**: standard Git tools will help us to understand the evolution of the SDK from a customer-focussed perspective, by simply `diff`'ing this single file\n- **Validation Against Source Code Interfaces**: either using runtime-build reflection or source-code annotation we can evolve language-specific tools that link the SDK-specific APIs back to canonical feature nodes, allowing us to navigate back and forth between the two\n\n#### Estate-wide Magic\n\n- **Customer Facing Feature Matrix**: We have the information to be able to contribute, with automation, to the contents of the [Ably Feature Support Matrix](https://ably.com/download/sdk-feature-support-matrix):\n  - built using a GitHub workflow hosted in a brand new intermediary repository, generating an artifact that can be consumed by the tools used by our developer education and documentation team (probably a public [npm](https://www.npmjs.com/) package)\n- **Full Feature Compliance Matrix**: Primarily for use by the Ably SDK Team, but (as with everything we do, [open for all](https://ably.com/blog/ably-values)) available to be viewed in the public domain. Likely to be an evolution of what you see assembled by [`build.js`](render/build.js) and uploaded by [the assemble workflow](../workflows/assemble.yml) to `sdk.ably.com`. Providing complete visibility over what features each SDK implements at an appropriate level of granularity.\n\n### Future Direction for the Client Library Features Specification\n\nThis single source file will remain our reference for:\n\n- protocol details, including interactions with SDK state and behaviours\n- SDK implementation details\n- conformed naming for types and their members\n- testing requirements (though it is anticipated that, at some point in the future, we will these from the scope of concern for this source file)\n\nSee [the `ably/specification` repository](https://github.com/ably/specification) for more details.\n\n## What makes a Feature?\n\n[The canonical feature list](sdk.yaml) does not represent an API, nor is it intended to form the basis for an IDL.\nIt is a user-facing list of human readable feature names, which are presented as a tree of nodes because it's logical to do so, and just happen to also be machine readable.\n\nTo warrant placement as a node within the tree, at any level, a Feature must represent or group together direct, user-facing functionality.\n\nNodes in the tree are not abstract. We do not have any concept of 'implements' or 'extends' attribution on Feature nodes, meaning that the only context a Feature node can imbue is that provided by its placement in the tree (i.e. its parent Feature nodes).\n\nA good litmus test is to consider what would be the implication, from an application developer's perspective, if the Feature node under consideration was removed from the tree. If there is no concrete, absolute, direct functionality that disappears as a result - isolated to the Feature node's context, only based on position in the tree - then it should not have been present in the tree, nor should it have been referred to as a Feature.\n\nAn example of something that intentionally does not appear in the tree as a Feature node is the concept of a `PaginatedResult`, otherwise known as the data type that offers APIs that provide support for results to be returned to the application in relatively small chunks referred to as pages (pagination).\nWe have Feature nodes that implicitly imply Pagination support, which will be specified by one the features spec points they reference, however we don't have an explicit Feature node that specifies Pagination as a discrete functionality in isolation.\nAn SDK will add support for abstract Pagination (perhaps using generics, where available) as an automatic requirement and consequence of implementing a feature that implies the need for Pagination support, from the features spec..\n\n## Feature Node Names\n\nThe names of feature nodes (those not prefixed with a dot '`.`' to denote them as properties) in [the canonical feature list](sdk.yaml) should conform to the following requirements:\n\n- not use abbreviations\n- use plural form only if it's strictly necessary - i.e.:\n  - use plural form when the concept being captured is _always_ dealing with many things - e.g. `Agent Identifier: Agents`, `REST: Statistics` and `Realtime: Push Notifications`\n  - use plural form when the plurality is utterly baked into the naming of the primary type involved - e.g. `Options: Token Details`\n  - do not use plural form when the feature links to a primary type and includes methods or properties that involve with that type in both singular and plural contexts - e.g. `REST: Push Notifications Administration: Device Registration`\n\nThis is so that we keep a consistent 'tone of voice', making feature names that are easily comprehensible by human readers and sit alongside one another congruously.\n\n## Feature Node Synopsis\n\nThere's a difficult balance to find here when writing these descriptions.\n\nWe don't want to be too prescriptive around API details such as:\n\n- names of interfaces, classes or properties\n- the nature of delivery - that is, whether synchronous or asynchronous - as that kind of language may be too prescriptive for some SDK settings\n- mechanisms for failure reporting - errors, exceptions, codes, etc..\n\nHowever, there is also a lot of prior art in our SDKs, so mention of particular phrases or API names can help with discovery for readers of this work.\n\nPrefixes such as \"Capability to\" and \"Support for\" should generally be avoided, in particular at the start of the first sentence of any given synopsis.\nThis is because the entire document is about capabilities to do \"X\", so additional wording such as \"Capability for the application to do X\" is superfluous and not helpful to the reader.\n\nConsistently use imperative, present tense where that makes sense (also known as 'imperative mood' in the context of git commit messages) - e.g.:\n\n- \"Provide a literal token\" rather than \"Providing a literal token\"\n- \"Return continuous message history\" rather than \"Used to return continuous message history\"\n\nAs we evolve this work we can hopefully add to this guidance around what should be included and what should be avoided.\n\n## Feature Node Dependencies\n\nA feature node is able to express that it `requires` one or more features in order to be able to be implemented in an SDK.\nThe following logical constraints should apply - a feature:\n\n- must only indicate it requires another feature if it cannot exist or otherwise _fully_ function without that other feature having also been implemented\n- cannot require one of its parent features, as that's implicit\n- should only require both the `REST` and `Realtime` features if both of them **must** be present in the SDK for the feature to work at all,\n  in other words:\n  - :green_circle: _needs both_: if it requires **both** `REST` **and** `Realtime` to be viable, then it should include them both in its `requires` property\n  - :red_circle: _needs one, the other, or both_: if it requires **either** `REST` **or** `Realtime` to be viable, then it must not include either of them in its `requires` property\n  - :green_circle: _needs just REST_: if it requires `REST` but does not require or otherwise relate to `Realtime`, then it should include `REST` in its `requires` property\n  - :green_circle: _needs just Realtime_: if it requires `Realtime` but does not require or otherwise relate to `REST`, then it should include `Realtime` in its `requires` property\n\nWhen a feature node 'A' indicates that it requires another feature 'B', then it's implied that any children of 'A' also require 'B'.\n\nThe `requires` property allows a feature to express which other feature(s) it requires using one or more references to feature nodes in the tree, where a reference is a string path with node names delimited by a colon followed by a space (`': '`).\n\nWe have chosen to use a colon within the delimiter because it's logical in human readable form - e.g.:\n\n    Service: Fallbacks: REST Follows Realtime\n\nThis is intentionally the same formatting that we use in the rendered view to represent a fully-qualified feature node path.\n\nThe implication of this choice of delimiter is that, in YAML, these node references - if referring to a non-root node - need to be quoted. e.g.:\n\n```yaml\n.requires:\n  - REST\n  - 'Debugging: Error Information'\n```\n\nWhere:\n\n- the `REST` feature node reference did not need to be quoted, as it's a root node, therefore a path with only one segment\n- the `Debugging: Error Information` feature node reference must be quoted, as it's a child of a root node, therefore a path with more than one segment\n\nWe will add checks in [#64](https://github.com/ably/features/issues/64).\n\n## Disincluded Features\n\n### `ClientOptions#logExceptionReportingUrl`\n\nSpecified by [TO3m](https://sdk.ably.com/builds/ably/specification/main/features/#TO3m)\nand [RSC20](https://sdk.ably.com/builds/ably/specification/main/features/#RSC20).\n\nWill be removed under [ably/docs#1381](https://github.com/ably/docs/issues/1381).\n\n## Contributing\n\nFor guidance on how to contribute to this project, see [CONTRIBUTING.md](CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fably%2Ffeatures","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fably%2Ffeatures","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fably%2Ffeatures/lists"}