Arquivos
Armazenamento de arquivos por conteúdo, com envio em partes para arquivos grandes.
Visão geral
Arquivos armazena o conteúdo binário da sua aplicação (imagens, documentos, exportações, gravações) em https://data.inovacc.dev, com envios em partes para tudo o que for grande. Ele oferece duas formas de endereçar um arquivo:
- por caminho, na pasta da sua aplicação:
PUT /v1/files/users/123/avatar.png, do jeito que um bucket de armazenamento na nuvem nomeia arquivos, com listagens por pasta, metadados do usuário e pastas compartilhadas com outras aplicações do seu espaço de trabalho; - por conteúdo, dentro de um banco de dados:
PUT /v1/databases/{db}/blobs/{sha256}, em que o próprio SHA-256 do arquivo é o seu nome, de modo que um registro de Dados pode apontar para ele com um campoblob.
O problema que ele resolve é manter arquivos junto dos seus dados sem operar armazenamento: a Inovacc escolhe onde os bytes vivem, verifica-os contra o hash, remove duplicatas dentro da sua pasta e os devolve com cabeçalhos que impedem que um arquivo baixado seja executado em um navegador.
Use Arquivos para tudo o que for bytes em vez de campos. Mantenha a descrição estruturada de um arquivo (proprietário, título, status) como um registro em Dados. Para tornar um arquivo pesquisável por significado, adicione-o a uma coleção de Conhecimento e busca vetorial.
Conceitos
A pasta da sua aplicação. Cada aplicação tem a sua própria pasta. A pasta é escolhida a partir da credencial, nunca da requisição: uma credencial vinculada a uma aplicação usa a pasta dessa aplicação, e uma credencial não vinculada a nenhuma aplicação recebe 403 application_required em toda rota de caminho. Os caminhos são UTF-8, de 1 a 1.024 bytes, separados por /, diferenciam maiúsculas de minúsculas, sem segmentos vazios, . ou ..; um caminho que ainda não esteja nessa forma é recusado, nunca reescrito silenciosamente.
Metadados. Uma escrita pode levar um Content-Type e cabeçalhos X-File-Meta-<name> próprios (2 KiB no total). Ambos voltam em toda leitura. Uma escrita substitui por inteiro o conteúdo, o tipo e os metadados do arquivo.
Hashes. Todo arquivo é identificado pelo seu SHA-256. Envie X-File-Sha256 com uma escrita e os bytes são conferidos contra ele (400 hash_mismatch, nada é armazenado). Dentro da pasta de uma aplicação, dois caminhos com os mesmos bytes compartilham uma única cópia armazenada; a cópia é mantida até que o último caminho seja removido. A deduplicação nunca atravessa aplicações ou organizações.
Blobs de banco de dados. Um blob é endereçado pelo SHA-256 em seu caminho dentro de um banco de dados. Enviá-lo de novo responde 200 em vez de 201. Qualquer pessoa com permissão de leitura no banco de dados que conheça o hash pode lê-lo: as regras de registros não se aplicam a blobs.
Pastas compartilhadas. Uma aplicação pode criar uma pasta team que aparece para toda aplicação com acesso como shared/team/.... Quem a criou é o proprietário e concede a outras aplicações do mesmo espaço de trabalho read ou read_write. Uma aplicação sem acesso não consegue saber que a pasta existe: toda operação responde 404.
Arquivos grandes. Até 100 MiB vão em uma única requisição. Acima disso, até 5 GiB, você envia em partes e depois vincula o resultado a um caminho (ou ele se torna o blob).
Como funciona
Toda chamada leva Authorization: Bearer <credential>; não há cabeçalho de organização, porque a sua organização e a aplicação vêm da credencial. A permissão verificada é de leitura, escrita ou exclusão de blobs. Uma página web pode usar essas rotas com uma chave publicável a partir de uma origem que a sua aplicação lista.
Escrita por caminho. PUT /v1/files/{path} com os bytes e um Content-Length (obrigatório). A resposta é 201 para um caminho novo ou 200 para uma substituição: {"path","size","sha256","content_type","updated_at","metadata"} e ETag: "<sha256>".
Leitura. GET /v1/files/{path} devolve o arquivo inteiro (intervalos não são suportados) com Content-Type, ETag, X-File-Sha256, X-File-Updated-At e os seus cabeçalhos X-File-Meta-*. Todo download também traz X-Content-Type-Options: nosniff, um Content-Security-Policy que o isola e Cache-Control: no-store, de modo que uma página HTML enviada nunca possa ser executada como se fosse o seu site. HEAD devolve apenas os cabeçalhos.
Listagem. GET /v1/files?prefix=photos/&delimiter=/ lista os arquivos diretamente sob uma pasta como items e cada subpasta uma única vez em prefixes. Siga next_cursor até que seja null: uma página pode ser menor que limit e ainda assim ter uma próxima.
Em partes. POST /v1/files-uploads/{sha256} inicia um envio (ou responde 200 com exists: true quando a sua pasta já contém esses bytes). Envie as partes de 1 a 10.000 com PUT .../{upload_id}/parts/{n}, cada uma entre 5 MiB e 100 MiB, exceto a última, e depois POST .../complete com a lista de partes e seus etags. A Inovacc lê o objeto inteiro de volta e confere o seu SHA-256 e o tamanho. Por fim, PUT /v1/files/{path} com X-File-Sha256 e corpo vazio dá a ele um caminho. Os blobs de banco de dados usam as mesmas quatro etapas em /v1/databases/{db}/blobs/{sha256}/uploads.
Envios, downloads e exclusões são registrados no Registro de atividade com o hash e o tamanho do arquivo.
Primeiros passos
Você precisa de uma chave secreta vinculada a uma aplicação, com permissões de blobs (Autenticação).
- Envie um arquivo.
PUT /v1/files/reports/2026-10.csvcom o arquivo como corpo eContent-Type: text/csv(veja os exemplos). A resposta é 201 com o seusha256. - Leia-o de volta.
GET /v1/files/reports/2026-10.csv. Os bytes chegam comETagigual ao hash do passo 1. - Liste a pasta.
GET /v1/files?prefix=reports/&delimiter=/. O seu arquivo está emitems. - Substitua-o. Faça
PUTno mesmo caminho com bytes novos. A resposta é 200, com um novosha256. - Exclua-o.
DELETE /v1/files/reports/2026-10.csvresponde 204; um segundoGETresulta em 404file_not_found.
Casos de uso
Fotos de perfil a partir do navegador. Um aplicativo web envia cada avatar para users/<id>/avatar.png com uma chave publicável e guarda o sha256 devolvido no registro do usuário, para que uma página perceba quando a imagem mudou.
Exportações compartilhadas com um aplicativo parceiro. Uma aplicação de relatórios cria a pasta compartilhada exports, concede read à aplicação de faturamento e grava arquivos mensais em shared/exports/. A aplicação de faturamento os lista e baixa; revogar a concessão tem efeito já na requisição seguinte dela.
Mídia grande com integridade. Uma ferramenta de vídeo calcula o hash de uma gravação de 2 GiB no cliente, envia-a em partes de 100 MiB e a conclui. A Inovacc só a armazena se o SHA-256 coincidir, de modo que uma transferência corrompida nunca se torna um arquivo.
Limites e preços
| Limite | Valor |
|---|---|
| Arquivo ou blob em uma requisição | 100 MiB, Content-Length obrigatório |
| Arquivo ou blob enviado em partes | 5 GiB; partes de 5 MiB a 100 MiB (exceto a última), numeradas de 1 a 10.000 |
| Caminho | 1.024 bytes |
| Prefixo de listagem | 256 bytes |
| Metadados por arquivo | 2 KiB |
| Página de listagem | 1 a 200 (padrão 50) |
| Nome da pasta compartilhada | 1 a 64 letras, dígitos, _ ou - |
| Taxa | 600 requisições por minuto por titular de credencial, por localização |
Preços: sob consulta.
Erros
| Status | Código | O que significa e o que fazer |
|---|---|---|
| 400 | invalid_path, invalid_prefix | O caminho ou prefixo não está na forma canônica; corrija do seu lado. |
| 400 | invalid_metadata | Content-Type ou X-File-Meta-* viola as regras ou excede 2 KiB. |
| 400 | hash_mismatch | Os bytes não correspondem ao SHA-256 que você enviou; nada foi armazenado. |
| 400 | invalid_part, invalid_limit, invalid_cursor, invalid_grantee | Corrija as partes do envio, a listagem ou a concessão. |
| 401 | invalid_credentials | Envie uma credencial válida. |
| 403 | application_required | As rotas de caminho exigem uma credencial vinculada a uma aplicação. |
| 403 | forbidden | Falta permissão, ou um beneficiário com read tentou escrever. |
| 404 | file_not_found, blob_not_found, share_not_found, upload_not_found | Não existe, ou você não tem acesso a ele. |
| 409 | already_exists, not_empty | O nome da pasta compartilhada já está em uso; esvazie a pasta antes de excluí-la. |
| 411 | length_required | Envie Content-Length. |
| 413 | payload_too_large | Mais de 100 MiB em uma requisição (use partes) ou mais de 5 GiB. |
| 429 | rate_limited | Diminua o ritmo. |
| 503 | service_unavailable | Tente novamente mais tarde. |
Boas práticas
- Envie
X-File-Sha256em toda escrita para que um envio danificado seja recusado em vez de armazenado. - Use partes acima de 100 MiB e comece com
POST .../uploads: ele respondeexists: truequando os bytes já estão lá. - Guarde o
sha256, não apenas o caminho, nos seus registros; ele diz exatamente a que conteúdo um registro se refere. - Siga
next_cursoraté o fim ao listar; páginas curtas são normais. - Conceda
read, a menos que um parceiro precise escrever, e revogue as concessões de que não precisa mais. - Não conte com blobs serem privados por regra: qualquer pessoa que possa ler o banco de dados e conheça o hash pode ler um blob.
Relacionados
- Dados: registros que apontam para arquivos com campos
blob - Registro de atividade: envios e downloads com seus hashes
- Conhecimento e busca vetorial: torne documentos pesquisáveis
- Autenticação, Erros, Limites
Autenticação
Toda chamada leva a sua chave; a sua organização vem dela. Veja o guia de autenticação.
AuthorizationEndpoints
PUT /v1/databases/{database}/blobs/{sha256}
GET /v1/databases/{database}/blobs/{sha256}
DELETE /v1/databases/{database}/blobs/{sha256}
POST /v1/databases/{database}/blobs/{sha256}/uploads
Exemplo
Linguagem
⋮
cURL
# The body is {} here: see parameters.
curl -X PUT "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}" \
-H "Authorization: Bearer $INOVACC_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'# The body is {} here: see parameters.
curl -X PUT "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}" \
-H "Authorization: Bearer $INOVACC_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
TypeScript
// The body is {} here: see parameters.
const body: Record<string, unknown> = {};
const url = "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}";
const response = await fetch(url, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());// The body is {} here: see parameters.
const body: Record<string, unknown> = {};
const url = "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}";
const response = await fetch(url, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());
Python
import json
import os
import urllib.request
# The body is {} here: see parameters.
body = {}
request = urllib.request.Request(
"https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}",
data=json.dumps(body).encode(),
method="PUT",
headers={
"User-Agent": "inovacc-python-sample",
"Authorization": "Bearer " + os.environ["INOVACC_API_KEY"],
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request) as response:
print(response.status, response.read().decode())import json
import os
import urllib.request
# The body is {} here: see parameters.
body = {}
request = urllib.request.Request(
"https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}",
data=json.dumps(body).encode(),
method="PUT",
headers={
"User-Agent": "inovacc-python-sample",
"Authorization": "Bearer " + os.environ["INOVACC_API_KEY"],
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request) as response:
print(response.status, response.read().decode())
Go
package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
const url = "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}"
// The body is {} here: see parameters.
const body = `{}`
func main() {
req, err := http.NewRequest("PUT", url, strings.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("INOVACC_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(res.Status, string(out))
}package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
const url = "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}"
// The body is {} here: see parameters.
const body = `{}`
func main() {
req, err := http.NewRequest("PUT", url, strings.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("INOVACC_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(res.Status, string(out))
}
Rust
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
// Cargo.toml: serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::var("INOVACC_API_KEY")?;
// The body is {} here: see parameters.
let body = serde_json::json!({});
let response = reqwest::blocking::Client::new()
.put("https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}")
.bearer_auth(api_key)
.json(&body)
.send()?;
println!("{} {}", response.status(), response.text()?);
Ok(())
}// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
// Cargo.toml: serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::var("INOVACC_API_KEY")?;
// The body is {} here: see parameters.
let body = serde_json::json!({});
let response = reqwest::blocking::Client::new()
.put("https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}")
.bearer_auth(api_key)
.json(&body)
.send()?;
println!("{} {}", response.status(), response.text()?);
Ok(())
}
JavaScript
// The body is {} here: see parameters.
const body = {};
const url = "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}";
const response = await fetch(url, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());// The body is {} here: see parameters.
const body = {};
const url = "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}";
const response = await fetch(url, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());
PHP
<?php
// The body is {} here: see parameters.
$body = <<<'JSON'
{}
JSON;
$curl = curl_init('https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}');
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('INOVACC_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($curl);
echo curl_getinfo($curl, CURLINFO_HTTP_CODE), ' ', $response, "\n";
curl_close($curl);<?php
// The body is {} here: see parameters.
$body = <<<'JSON'
{}
JSON;
$curl = curl_init('https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}');
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('INOVACC_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($curl);
echo curl_getinfo($curl, CURLINFO_HTTP_CODE), ' ', $response, "\n";
curl_close($curl);
Ruby
require "net/http"
require "uri"
uri = URI('https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}')
# The body is {} here: see parameters.
body = <<~'JSON'
{}
JSON
request = Net::HTTP::Put.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('INOVACC_API_KEY')}"
request["Content-Type"] = "application/json"
request.body = body
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts "#{response.code} #{response.body}"require "net/http"
require "uri"
uri = URI('https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}')
# The body is {} here: see parameters.
body = <<~'JSON'
{}
JSON
request = Net::HTTP::Put.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('INOVACC_API_KEY')}"
request["Content-Type"] = "application/json"
request.body = body
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts "#{response.code} #{response.body}"
Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("INOVACC_API_KEY");
// The body is {} here: see parameters.
String body = "{}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("INOVACC_API_KEY");
// The body is {} here: see parameters.
String body = "{}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}
C#
using System.Text;
// The body is {} here: see parameters.
var body = "{}";
var url = "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}";
var apiKey = Environment.GetEnvironmentVariable("INOVACC_API_KEY");
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Put, url);
request.Headers.Add("Authorization", $"Bearer {apiKey}");
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");using System.Text;
// The body is {} here: see parameters.
var body = "{}";
var url = "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}";
var apiKey = Environment.GetEnvironmentVariable("INOVACC_API_KEY");
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Put, url);
request.Headers.Add("Authorization", $"Bearer {apiKey}");
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
Kotlin
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
fun main() {
val apiKey = System.getenv("INOVACC_API_KEY")
// The body is {} here: see parameters.
val body = "{}"
val request = HttpRequest.newBuilder()
.uri(URI.create("https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString(body))
.build()
val response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString())
println("${response.statusCode()} ${response.body()}")
}import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
fun main() {
val apiKey = System.getenv("INOVACC_API_KEY")
// The body is {} here: see parameters.
val body = "{}"
val request = HttpRequest.newBuilder()
.uri(URI.create("https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString(body))
.build()
val response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString())
println("${response.statusCode()} ${response.body()}")
}
Swift
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
// The body is {} here: see parameters.
let body = #"""
{}
"""#
let apiKey = ProcessInfo.processInfo.environment["INOVACC_API_KEY"] ?? ""
let url = URL(string: "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}")!
var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(body.utf8)
let (data, response) = try await URLSession.shared.data(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
print(status, String(decoding: data, as: UTF8.self))import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
// The body is {} here: see parameters.
let body = #"""
{}
"""#
let apiKey = ProcessInfo.processInfo.environment["INOVACC_API_KEY"] ?? ""
let url = URL(string: "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}")!
var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(body.utf8)
let (data, response) = try await URLSession.shared.data(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
print(status, String(decoding: data, as: UTF8.self))
Detalhes da fonte
- Id
- identity/component-taxonomy/capabilities#files
- Repositório
- identity
- Caminho
- contracts/component-taxonomy/catalog/capabilities.json
- Commit
- 08ef3cd75d82
- Id
- identity/component-taxonomy/quickstart#files
- Repositório
- identity
- Caminho
- contracts/component-taxonomy/catalog/capabilities.json
- Commit
- 08ef3cd75d82