ores.storage.objects

Table of Contents

Object storage has no entity: an object is a bucket, an opaque key and a byte string, and the store never parses any of the three. That is why the surface is an operation model rather than an entity model, and why the messages below carry no tenancy and no server-owned field.

Four operations are modelled. There is deliberately no exists operation: the protocol has no such verb, and existence is a read, so get reports absence in its own reply and the HTTP projection answers HEAD without a body. There is no counter either, because a count is a property of a list.

The bucket is the caller's concern. Storage holds no bucket name, no registry and no allow-list, so the bucket arrives as part of the request and the server validates it as a key segment rather than checking it against a list.

The handler that serves these operations stays hand-written beside this model, because an operation model generates no service handler. It authenticates the caller, checks the operation's permission code, and calls ores.storage.core.

1. Includes

#include <cstdint>
#include <string>
#include <string_view>
#include <vector>

2. Messages

2.1. put_objects_request

/**
 * @brief Writes one object, replacing whatever was at the key.
 *
 * A put carries the whole object: there is no append and no partial write, so
 * an object is either the old value or the new one. The content travels in the
 * message only when it is small enough to; the bulk path is HTTP, and the two
 * leave the same object at the same bucket and key.
 */

2.1.1. bucket

/**
 * @brief The allocation the object lives in. Named by the caller.
 */

2.1.2. key

/**
 * @brief The object's name within the bucket. Opaque: storage never parses it.
 */

2.1.3. content

/**
 * @brief The object's bytes.
 */

2.1.4. content_encoding

/**
 * @brief Empty for raw bytes, or the encoding the caller applied.
 *
 * A caller may compress before it puts, and it must say so here, because
 * nothing on the wire marks an object as compressed.
 */

2.2. put_objects_response

/**
 * @brief The outcome of the write.
 */

2.2.1. success

2.2.2. message

2.2.3. size_bytes

/**
 * @brief How many bytes the store now holds under the key.
 */

2.3. get_objects_request

/**
 * @brief Reads one object's metadata, and its value when asked for.
 *
 * The same operation answers existence: a key that is not there comes back as
 * a reply that says so, which is why the surface needs no separate verb for it.
 */

2.3.1. bucket

2.3.2. key

2.3.3. include_content

/**
 * @brief Whether the reply should carry the object's bytes.
 */

2.4. get_objects_response

/**
 * @brief The object, or the news that it is not there.
 */

2.4.1. success

2.4.2. message

2.4.3. found

/**
 * @brief False when the bucket holds no object at the key.
 */

2.4.4. size_bytes

2.4.5. content

/**
 * @brief The object's bytes, present only when the request asked for them.
 */

2.5. delete_objects_request

/**
 * @brief Removes one object.
 */

2.5.1. bucket

2.5.2. key

2.6. delete_objects_response

/**
 * @brief The outcome of the removal.
 */

2.6.1. success

2.6.2. message

2.6.3. removed

/**
 * @brief False when there was nothing at the key to remove.
 */

2.7. list_objects_request

/**
 * @brief Asks for a page of the objects in one bucket.
 *
 * The prefix is a filter over keys, not a directory: storage treats a key as
 * opaque, so a caller that wants everything under a prefix asks for it by
 * prefix and never by path.
 */

2.7.1. bucket

2.7.2. prefix

/**
 * @brief Only keys that start with this are returned. Empty means every key.
 */

2.7.3. offset

2.7.4. limit

2.8. object_summary

/**
 * @brief One object in a listing, without its value.
 */

2.8.1. key

2.8.2. size_bytes

2.9. list_objects_response

/**
 * @brief The page of objects, with the total the caller is paging through.
 */

2.9.1. success

2.9.2. message

2.9.3. objects

2.9.4. total_available_count

3. See also

Emacs 29.3 (Org mode 9.6.15)