'use strict';

// SharedSecret — a secret the owner has published to the shared namespace so it
// can be shared with other users and/or downstream apps.
//
// The secret DATA lives in OpenBao at `secret/shared/<ownerUid>/<slug>` (KV-v2),
// never in the DB. This row is metadata only (owner + slug + description) and is
// the source of truth for the UI (which shares exist). ACCESS CONTROL is enforced
// entirely by OpenBao ACL policies: the owner's `user-<uid>` policy grants full
// R/W on `secret/shared/<ownerUid>/*`, and each grantee's policy content is
// edited to add `read` on the exact shared path (see vault_broker.js — policy
// content is parsed live at token use, so a grant takes effect immediately with
// no token re-mint). `secretId` on SharedSecretGrant links grantees to this row.
//
// `slug` is unique and immutable in practice — it is embedded in the shared path
// and in grantee policy rules, so changing it would require rewriting policies.
// Like PluginInstance, there is no ORM auto-timestamp hook: route handlers stamp
// created_by/on + updated_by/on on every write. `id` (uuid) is generated by the
// ORM on create.

const { Model } = require('@simpleworkjs/orm');

class SharedSecret extends Model {
  static fields = {
    id: { type: 'uuid', primaryKey: true },
    // Human slug embedded in the OpenBao path: secret/shared/<ownerUid>/<slug>.
    // Unique so two owners can't collide on the same shared path.
    slug: { type: 'string', isRequired: true, unique: true, min: 1, max: 64 },
    // The publishing user's uid — also the shared path's namespace segment.
    ownerUid: { type: 'string', isRequired: true, min: 1, max: 64 },
    // Optional human description shown in the Shared tab.
    description: { type: 'text' },
    // Audit stamps (set by the route handler, not by an ORM hook).
    created_by: { type: 'string' },
    created_on: { type: 'integer' },
    updated_by: { type: 'string' },
    updated_on: { type: 'integer' },
  };

  // Full OpenBao KV-v2 path for this shared secret (logical path, no data/metadata).
  static pathFor(ownerUid, slug) {
    return `shared/${ownerUid}/${slug}`;
  }

  path() {
    return SharedSecret.pathFor(this.ownerUid, this.slug);
  }

  // Look up by slug (unique). Returns the row or null.
  static async getBySlug(slug) {
    const rows = await this.list({ where: { slug } });
    return rows[0] || null;
  }
}

module.exports = { SharedSecret };
