# UnifiedFiler Host側組み込み仕様書

Product Version: 1.0.0  
Public API Version: 1.0  
Backend API Contract: 1.0  
Development Baseline: dev-2.1.0

本書は、UnifiedFiler を Host システムへ組み込む側のための仕様書である。Host は UnifiedFiler の内部 View や DOM 構造へ直接依存せず、公開 Control API、Service API、Adapter API、Registry API、Event API を通して連携する。

## 1. 適用範囲

本書は以下の組み込み先を想定する。

- WebDesktop / AppHost
- Viewer / Editor / Office 系アプリ
- 業務システムの添付ファイル管理
- Tools / Workspace 系アプリ
- PHP / NodeJS Backend API と連携するファイル管理画面
- Google Drive を frontend-only で扱うファイル操作画面

UnifiedFiler は Host そのものではない。起動管理、Window 管理、認証、テナント、権限、共通メニュー、アプリ間連携は Host 側の責務である。

## 2. Host側の責務

| 項目 | Host側の責務 |
|---|---|
| 配置 | UnifiedFiler パッケージルートを静的アセットとして配置する。 |
| ライブラリ読込 | jQuery 2.1.4、jQuery UI 1.12.1、RequireJS、必要なOSSを読み込む。 |
| Theme読込 | `themes/default/unified-filer.css` を読み込む。 |
| RequireJS alias | `UnifiedFiler` などの alias を `scripts/` へ向ける。 |
| 起動 | `UnifiedFiler.createExplorer()` などの Control API を呼び出す。 |
| 認証 | Hostユーザー、テナント、権限情報を管理する。 |
| Backend接続 | Backend API endpoint、認証ヘッダ、Host context を設定する。 |
| Google Drive設定 | API Key、OAuth Client ID、App ID、Scope、Authorized Origin を用意する。 |
| 権限制御 | Host権限を options / PermissionPolicy / Backend API へ反映する。 |
| アプリ連携 | `fileOpened` 等のEventを受け、Viewer / Editor等を起動する。 |
| 受入確認 | Demoと実Host上で回帰確認を行う。 |

## 3. 必須OSSと読込順

Host は OSS を UnifiedFiler より先に classic `<script>` で読み込む。ESM bundle は不要である。

```html
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
<link rel="stylesheet" href="/assets/unified_filer/themes/default/unified-filer.css">

<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.js"></script>
```

Font Awesome は推奨だが必須ではない。未読込の場合もテキストまたはfallback iconで操作可能にする。

## 4. 配置とRequireJS alias

推奨配置例である。

```text
/assets/unified_filer/
  scripts/
  themes/
  demo/
  docs/
  samples/
  README.txt
  VERSION.json
```

Host 側 RequireJS 設定例である。

```javascript
require.config({
    paths: {
        UnifiedFiler: '/assets/unified_filer/scripts'
    }
});
```

パッケージ内部の AMD 依存は相対パスで記述されているため、Host は `UnifiedFiler/main` の alias のみを基本設定すればよい。

## 5. バージョン確認仕様

Host は実行時に以下を確認できる。

```javascript
require(['UnifiedFiler/main'], function (UnifiedFiler) {
    console.log(UnifiedFiler.productVersion);      // '1.0.0'
    console.log(UnifiedFiler.developmentVersion);  // 'dev-2.1.0'
    console.log(UnifiedFiler.apiVersion);          // '1.0'
    console.log(UnifiedFiler.contractVersion);     // '1.0'
    console.log(UnifiedFiler.buildVersion);        // build identifier
});
```

Host の互換性判定は、原則として `productVersion` と `apiVersion` を基準にする。`developmentVersion` は開発履歴・調査用であり、製品互換判定には使わない。

## 6. Control API組み込み方式

Host は内部 jQuery View を直接操作せず、Control API を使う。

### 6.1 FileExplorer

```javascript
require(['UnifiedFiler/main'], function (UnifiedFiler) {
    var explorer = UnifiedFiler.createExplorer('#fileExplorer', {
        language: 'ja',
        theme: 'default',
        defaultStorage: 'appStorage',
        storageTypes: ['appStorage', 'localDisk', 'backendApi', 'googleDrive'],
        hostProfile: 'unifiedDesktop',
        enablePreview: true,
        enableMetadata: true,
        enableRecentFiles: true,
        enableFavorites: true,
        showStorageSelector: true,
        treeStorageMode: 'all'
    });

    explorer.on('fileOpened', function (event) {
        // Host側でViewer / Editor / AppLauncherを起動する。
        window.AppHost.openFile(event.entry);
    });

    explorer.mount();
});
```

### 6.2 FilePicker

```javascript
UnifiedFiler.openPicker({
    language: 'ja',
    hostProfile: 'viewer',
    defaultStorage: 'appStorage',
    storageTypes: ['appStorage', 'localDisk', 'googleDrive'],
    selectionType: 'file',
    allowMultiple: false,
    allowedExtensions: ['.txt', '.md', '.json'],
    enablePreview: true,
    showFolderTree: true
}).then(function (result) {
    console.log(result.entries || result);
});
```

### 6.3 FileSaver

```javascript
UnifiedFiler.openSaver({
    language: 'ja',
    hostProfile: 'editor',
    defaultStorage: 'appStorage',
    storageTypes: ['appStorage', 'localDisk', 'backendApi', 'googleDrive'],
    workflow: 'saveAs',
    defaultFileName: 'document.txt',
    data: 'Hello UnifiedFiler',
    mimeType: 'text/plain',
    showFolderTree: true
}).then(function (saveResult) {
    console.log(saveResult);
});
```

## 7. Host Profile仕様

Host は用途に応じて `hostProfile` を指定する。

| Profile | 主な用途 |
|---|---|
| `default` | 汎用既定値。 |
| `unifiedDesktop` | デスクトップ型Host上のファイル操作。 |
| `viewer` | 読み取り・Preview中心。 |
| `editor` | Open / Save / Save As中心。 |
| `office` | Office系アプリのOpen / Export / Save As。 |
| `package` | native package保存・読込。 |
| `ownersReform` | 業務添付ファイル管理。 |
| `sappaneTools` | Tools / DokuWiki / workspace連携。 |

Profile は初期値のプリセットであり、Host は個別 options で上書きしてよい。

## 8. Event連携仕様

Control は Host へ Event を通知する。Host は `control.on(name, handler)` を使う。

代表Eventである。

| Event | 用途 |
|---|---|
| `mounted` | Controlが初期化された。 |
| `storageChanged` | Storageが変更された。 |
| `folderChanged` | 現在フォルダが変更された。 |
| `selectionChanged` | 選択が変更された。 |
| `fileOpened` | ファイルを開く要求。 |
| `fileSaved` | 保存完了。 |
| `beforeCommand` | Command実行前。 |
| `afterCommand` | Command実行後。 |
| `commandError` | Commandエラー。 |
| `commandStateChanged` | Toolbar / ContextMenu等の状態更新。 |
| `metadataUpdated` | Metadata更新。 |
| `previewRendered` | Preview描画完了。 |
| `uploadStarted` / `uploadProgress` / `uploadCompleted` | Upload進捗。 |

Host は、ファイルを直接開くのではなく、`fileOpened` を受けて適切なViewer/Editorを起動する設計を推奨する。

## 9. Command連携仕様

Host は `exec()` で操作を実行できる。

```javascript
explorer.exec('refresh');
explorer.exec('newFolder');
explorer.exec('rename');
explorer.exec('delete');
explorer.exec('upload');
explorer.exec('download');
explorer.exec('createItem', { typeId: 'dokuwiki-page' });
```

Command の有効・無効状態は以下で取得できる。

```javascript
var stateMap = explorer.getCommandStateMap();
console.log(stateMap.rename.enabled);
```

Toolbar、ContextMenu、Shortcut、Host `exec()` は同じ CommandRegistry を経由する。

## 10. Storage構成仕様

UnifiedFiler は StorageAdapter を差し替えて使う。

| Storage | Adapter | Host側の準備 |
|---|---|---|
| App Storage | `IndexedDbAdapter` | なし。ブラウザIndexedDBを使用。 |
| This Device | `LocalDiskAdapter` | File System Access API対応ブラウザ。 |
| Backend API | `BackendApiAdapter` | endpoint / 認証 / Host context。 |
| Google Drive | `GoogleDriveAdapter` | API Key / Client ID / App ID / Scope。 |

HostがServiceとAdapterを明示構成する例である。

```javascript
require([
    'UnifiedFiler/main'
], function (UnifiedFiler) {
    var registry = new UnifiedFiler.services.StorageRegistry();

    var appStorage = new UnifiedFiler.adapters.IndexedDbAdapter({
        id: 'appStorage',
        label: 'App Storage'
    });

    var localDisk = new UnifiedFiler.adapters.LocalDiskAdapter({
        id: 'localDisk',
        label: 'This Device'
    });

    var backendApi = new UnifiedFiler.adapters.BackendApiAdapter({
        id: 'backendApi',
        label: 'Backend API',
        baseUrl: '/api/files',
        workspaceId: window.HostContext.workspaceId,
        ownerObjectType: window.HostContext.ownerObjectType,
        ownerObjectId: window.HostContext.ownerObjectId,
        permissionScope: window.HostContext.permissionScope
    });

    registry.register(appStorage);
    registry.register(localDisk);
    registry.register(backendApi);
});
```

## 11. Google Drive frontend-only仕様

Google Drive は Hostのサーバを経由せず、ブラウザJavaScriptから直接連携する。

Host側で必要なものは以下である。

- Google Cloud Project
- Browser API Key
- OAuth Web Client ID
- App ID / Project Number
- Authorized JavaScript origins
- 必要Scope

設定例である。

```javascript
var googleDriveOptions = {
    id: 'googleDrive',
    label: 'Google Drive',
    apiKey: 'YOUR_BROWSER_API_KEY',
    clientId: 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com',
    appId: 'YOUR_GOOGLE_CLOUD_PROJECT_NUMBER',
    scopes: ['https://www.googleapis.com/auth/drive'],
    authMode: 'gis-token',
    uploadStrategy: 'auto',
    conflictMode: 'rename',
    enablePicker: true,
    supportsAllDrives: true,
    includeItemsFromAllDrives: true
};
```

`drive.file` scope は、アプリが作成したファイルまたはユーザーがPicker等で明示したファイル中心の運用に向く。汎用FileExplorerとして既存Drive全体を扱う場合は、Host側で `https://www.googleapis.com/auth/drive` の利用可否を検討する。

Client secret、Backend proxy、server-side upload endpoint は使用しない。

## 12. Backend API Host Context仕様

Backend API連携時、HostはContextをBackendへ渡す。

代表Contextである。

| Field | 意味 |
|---|---|
| `workspaceId` | Workspace / tenant area。 |
| `ownerObjectType` | 添付先オブジェクト種別。 |
| `ownerObjectId` | 添付先オブジェクトID。 |
| `permissionScope` | Host権限スコープ。 |
| `userId` | Backend側認証で必要な場合。 |

HTTP headerとしては以下を利用できる。

```text
X-Workspace-Id
X-Owner-Object-Type
X-Owner-Object-Id
X-Permission-Scope
X-UnifiedFiler-Contract-Version
```

Backend APIの詳細は `docs/BACKEND_API_CONTRACT.md` を参照する。

## 13. Permission / Capability仕様

Hostの権限は以下の流れで反映する。

```text
Host User / Role / Permission
  -> UnifiedFiler options / Backend API context
  -> PermissionPolicyService / Adapter capability
  -> CommandRegistry state
  -> Toolbar / ContextMenu / Inline action enabled state
```

代表Capabilityである。

```javascript
{
    canRead: true,
    canWrite: true,
    canRename: true,
    canDelete: false,
    canCreateFolder: true,
    canUpload: true,
    canDownload: true,
    canExport: true,
    canShare: false,
    canPreview: true
}
```

Hostが read-only 画面を作る場合は、`readOnly: true` またはHost profile / Backend capabilityで書き込み系Commandを無効化する。

## 14. CreateType拡張仕様

Hostは新規作成メニューに独自タイプを追加できる。

```javascript
explorer.registerCreateType({
    id: 'dokuwiki-page',
    kind: 'file',
    label: 'DokuWiki Page',
    iconClass: 'fa fa-file-text-o',
    defaultName: 'new-page.txt',
    mimeType: 'text/plain',
    content: '====== New Page ======\n\n'
});

explorer.exec('createItem', { typeId: 'dokuwiki-page' });
```

高度な生成処理は `create(context)` を使用する。

```javascript
explorer.registerCreateType({
    id: 'unified-model',
    kind: 'file',
    label: 'Unified Model',
    defaultName: 'new-model.umdlx',
    mimeType: 'application/vnd.itoolkits.umdlx',
    create: function (context) {
        return {
            name: context.name,
            mimeType: 'application/vnd.itoolkits.umdlx',
            content: JSON.stringify({ manifest: { type: 'umdlx', version: '1.0' } }, null, 2)
        };
    }
});
```

## 15. PreviewProvider拡張仕様

Hostは独自ファイルタイプのPreview Providerを登録できる。

```javascript
explorer.registerPreviewProvider({
    id: 'umdlx-preview',
    label: 'Unified Model Preview',
    extensions: ['.umdlx'],
    priority: 100,
    trustedHtml: true,
    render: function (context) {
        return context.read().then(function (result) {
            return result.data.text();
        }).then(function (text) {
            var model = JSON.parse(text || '{}');
            return {
                html: '<div class="uf-host-preview"><h3>' +
                    context.escape(model.title || context.entry.name) +
                    '</h3></div>',
                trustedHtml: true
            };
        });
    }
});
```

Previewはセキュリティ影響が大きいため、Hostは不明なHTMLを `trustedHtml: true` にしない。必要に応じて sandbox preview または escape済みHTMLを利用する。

## 16. Metadata連携仕様

Metadata編集UIは、Host固有の情報を扱える。

代表項目である。

- `category`
- `appId`
- `tenantId`
- `workspaceId`
- `ownerObjectType`
- `ownerObjectId`
- `custom JSON`

Backend APIを使う場合、HostはこれらをBackend側の権限・検索・添付関連付けに利用できる。

## 17. Security Policy Host要求

Hostは以下を満たす必要がある。

- `file://` ではなく HTTP / HTTPS 配信で動作させる。
- Backend APIでは path traversal を拒否する。
- 危険拡張子、MIME不一致、大容量upload、ZIP bombをBackend側でも検査する。
- HTML previewをHost権限で無条件に信頼しない。
- Google OAuth Client secretをブラウザへ含めない。
- tenant / workspace / owner object の権限確認はBackend側で必ず行う。

UnifiedFilerの `SecurityPolicyService` はFrontend側の防御であり、Backendの権限確認を代替しない。

## 18. Host組み込み受入チェックリスト

| 区分 | 確認項目 |
|---|---|
| 配置 | Host上で `scripts/main.js` をRequireJS aliasから読み込める。 |
| OSS | jQuery 2.1.4 / jQuery UI 1.12.1 / RequireJSで動作する。 |
| Theme | UnifiedFiler CSSが読み込まれている。 |
| Version | `productVersion` / `apiVersion` を確認できる。 |
| Explorer | list / open / preview / metadata / rename / delete が期待通り。 |
| Picker | folder tree / file list / preview / selection が期待通り。 |
| Saver | saveAs / export / packageSave が期待通り。 |
| LocalDisk | This DeviceでローカルフォルダAttach方式が動作する。 |
| AppStorage | IndexedDB保存・一覧・削除が動作する。 |
| Backend API | contract v1.0に沿って認証・Context付きで動作する。 |
| Google Drive | OAuth / list / upload / rename / export / Shared Drivesを実環境確認する。 |
| Commands | Toolbar / ContextMenu / Shortcut / Host exec が同じ結果になる。 |
| CreateType | Host独自の新規タイプを登録・作成できる。 |
| PreviewProvider | Host独自Previewを登録・表示できる。 |
| Permission | read-onlyや削除不可権限がUIへ反映される。 |
| Security | 危険ファイル・大容量・HTML・ZIPに対する制限が効く。 |
| Console | 主要操作でConsole errorがない。 |

## 19. 関連ドキュメント

- `docs/API.md`
- `docs/PUBLIC_API_CONTRACT.md`
- `docs/HOST_INTEGRATION.md`
- `docs/HOST_APP_INTEGRATION_PRODUCT_1_0.md`
- `docs/BACKEND_API_CONTRACT.md`
- `docs/GOOGLE_DRIVE_BROWSER_CLIENT.md`
- `docs/SECURITY_POLICY.md`
- `docs/REGRESSION_TESTS.md`
- `docs/VERSIONING_POLICY.md`

